MySQL transactions with schema modification statements (DDL)? - mysql

Despite commit or rollback, the change is "commited" in both cases.
Commit:
START TRANSACTION;
ALTER TABLE `bank` CHANGE COLUMN `bank_active` `bank_activated` BOOLEAN NOT NULL;
COMMIT;
Rollback:
START TRANSACTION;
ALTER TABLE `bank` CHANGE COLUMN `bank_active` `bank_activated` BOOLEAN NOT NULL;
ROLLBACK;
Need to build an automatic updater, that includes database's schema and data updates, and would like to group everything into a transaction, so in case anything goes wrong, just fix the statements and run again.
Is it possible to rollback DDL statements within transactions?
Thank you

BEGIN in some contexts is the same as START TRANSACTION.
phpmyadmin performs one query at a time unless you put the batch in the window for such. Try that.
(And SET autocommit = 0 is irrelevant because of the explicit START.)
Edit
Since the "transaction" really had a DDL statement, my 'answer' is irrelevant.
DDLs cannot be rolled back: https://dev.mysql.com/doc/refman/5.7/en/cannot-roll-back.html

Related

Why can I use INSERT without any START TRANSACTION nor COMMIT/ROLLBACK with autocommit = 0 in mysql?

So I am trying to understand more about the autocommit statement in MySQL and I am having some trouble understanding why, after I use SET autocommit = 0; and try to run an INSERT without any START TRANSACTION and no COMMIT/ROLLBACK at the end it still inserts it into the table?
For what I understood, if the autocommit is equal to 1, it will commit automatically therefore it would make sense, but I set my autocommit to zero, therefore if I dont use any START TRANSACTION with COMMIT or ROLLBACK block surronding the insert it shouldnt work right?
I know there are some DML that commit automatically and i know that DDL statements do it as well, but in this case INSERT seems not to be any of the DML statements that does that.
The code goes as follow:
SET autocommit = 0;
SELECT ##autocommit; --It returns 0
-- No START TRANCATION
INSERT INTO example(first_name, last_name) VALUES ('TEST', 'TSET');
-- No COMMIT nor ROLLBACK
Any ideas?
Thanks in advance!
You see these rows in current session - but you'll not see them from another session.
Look:
Compare timestamps...

In InnoDB,is all sql in the transaction?

I seems have a wrong idea that :
update table_name set id=222 where id >333;
my old opinion is above single sql without begin and commit will not start a transaction.
but it seems wrong.
But when i read the mysql doc,i found that seems that all sql will in a transaction.if you do not explicit use begin and commit,it will start transaction implicit in InnoDB.
In InnoDB, all user activity occurs inside a transaction. If autocommit mode is enabled, each SQL statement forms a single transaction on its own. By default, MySQL starts the session for each new connection with autocommit enabled, so MySQL does a commit after each SQL statement if that statement did not return an error. If a statement returns an error, the commit or rollback behavior depends on the error. See Section 14.21.4, “InnoDB Error Handling”.
my question :
Is all sql will ececute in the transaction ,no matter whether do you use begin and commit explicitly.
it will be executed in single transactions - unless grouping statements with START TRANSACTION & COMMIT (the autocommit configuration will then be ignored, no matter it's value). SET autocommit = 0/1 can be used to control the level of isolation on-the-fly. there's also a configuration option for that, in order to change the behavior globally:
[mysqld]
autocommit=0
the documentation for "Server System Variables" explains it in detail:
The autocommit mode. If set to 1, all changes to a table take effect immediately. If set to 0, you must use COMMIT to accept a transaction or ROLLBACK to cancel it. If autocommit is 0 and you change it to 1, MySQL performs an automatic COMMIT of any open transaction. Another way to begin a transaction is to use a START TRANSACTION or BEGIN statement.

Does MySQL use transaction in a single DML modified data with autocommit?

I'm confused with transaction and autocommit. But there's no documents explains what MySQL autocommit do.
If autocommit on, every INSERT UPDATE DELETE statement will take effect immediately. Does MySQL auto start a transaction to do this?
If not, what's MySQL do? What's the difference to transaction?
In my view:
A statement
INSERT INTO ...
with autocommit on equals to
START TRANSACTION;
INSERT INTO ...;
COMMIT;
with autocommit off.
The two statements in anytime any condition takes the same action.
Is it right?
firstly, you have to know, that most MySQL Storage Engines do not support transactions. for example, InnoDB supports, but MyISAM - not.
In InnoDB, you can use transactions by 2 way:
implicit
START TRANSACTION;
INSERT/UPDATE/DELETE
COMMIT;
explicit
via SET autocommit off
both of them provide the same result

InnoDb transactions with create statements

Are sql statements such as CREATE TABLE tbl_name ..... allowed in transactions.
For example:
begin;
CREATE TABLE .......;
sdfghjk;
rollback;
The table is still created despite a statement in the transaction failing, and a rollback at the end. Is there a way to prevent the table from being created if a statement in the transaction fails?
DDL statements are allowed within transactions, but are not generally impacted by the transactions. From the MySQL Documentation on what can and cannot be rolled back:
Some statements cannot be rolled back. In general, these include data
definition language (DDL) statements, such as those that create or
drop databases, those that create, drop, or alter tables or stored
routines.
You should design your transactions not to include such statements. If
you issue a statement early in a transaction that cannot be rolled
back, and then another statement later fails, the full effect of the
transaction cannot be rolled back in such cases by issuing a ROLLBACK
statement.
Source
If you still need to use table you can do create temporary table..... It doesn't commit transaction but will be deleted when connection will be closed.

Difference between SET autocommit=1 and START TRANSACTION in mysql (Have I missed something?)

I am reading up on transactions in MySQL and am not sure whether I have grasped something specific correctly, and I want to be sure I understood that correctly, so here goes. I know what a transaction is supposed to do, I'm just not sure whether I understood the statement semantics or not.
So, my question is, is anything wrong, (and, if that is the case, what is wrong) with the following:
By default, autocommit mode is enabled in MySQL.
Now, SET autocommit=0; will begin a transaction, SET autocommit=1; will implicitly commit. It is possible to COMMIT; as well as ROLLBACK;, in both of which cases autocommit is still set to 0 afterwards (and a new transaction is implicitly started).
START TRANSACTION; will basically SET autocommit=0; until a COMMIT; or ROLLBACK; takes place.
In other words, START TRANSACTION; and SET autocommit=0; are equivalent, except for the fact that START TRANSACTION; does the equivalent of implicitly adding a SET autocommit=1; after COMMIT; or ROLLBACK;
If that is the case, I don't understand http://dev.mysql.com/doc/refman/5.5/en/set-transaction.html#isolevel_serializable - seeing as having an isolation level implies that there is a transaction, meaning that autocommit should be off anyway?
And if there is another difference (other than the one described above) between beginning a transaction and setting autocommit, what is it?
Being aware of the transaction (autocommit, explicit and implicit) handling for your database can save you from having to restore data from a backup.
Transactions control data manipulation statement(s) to ensure they are atomic. Being "atomic" means the transaction either occurs, or it does not. The only way to signal the completion of the transaction to database is by using either a COMMIT or ROLLBACK statement (per ANSI-92, which sadly did not include syntax for creating/beginning a transaction so it is vendor specific). COMMIT applies the changes (if any) made within the transaction. ROLLBACK disregards whatever actions took place within the transaction - highly desirable when an UPDATE/DELETE statement does something unintended.
Typically individual DML (Insert, Update, Delete) statements are performed in an autocommit transaction - they are committed as soon as the statement successfully completes. Which means there's no opportunity to roll back the database to the state prior to the statement having been run in cases like yours. When something goes wrong, the only restoration option available is to reconstruct the data from a backup (providing one exists). In MySQL, autocommit is on by default for InnoDB - MyISAM doesn't support transactions. It can be disabled by using:
SET autocommit = 0
An explicit transaction is when statement(s) are wrapped within an explicitly defined transaction code block - for MySQL, that's START TRANSACTION. It also requires an explicitly made COMMIT or ROLLBACK statement at the end of the transaction. Nested transactions is beyond the scope of this topic.
Implicit transactions are slightly different from explicit ones. Implicit transactions do not require explicity defining a transaction. However, like explicit transactions they require a COMMIT or ROLLBACK statement to be supplied.
Conclusion
Explicit transactions are the most ideal solution - they require a statement, COMMIT or ROLLBACK, to finalize the transaction, and what is happening is clearly stated for others to read should there be a need. Implicit transactions are OK if working with the database interactively, but COMMIT statements should only be specified once results have been tested & thoroughly determined to be valid.
That means you should use:
SET autocommit = 0;
START TRANSACTION;
UPDATE ...;
...and only use COMMIT; when the results are correct.
That said, UPDATE and DELETE statements typically only return the number of rows affected, not specific details. Convert such statements into SELECT statements & review the results to ensure correctness prior to attempting the UPDATE/DELETE statement.
Addendum
DDL (Data Definition Language) statements are automatically committed - they do not require a COMMIT statement. IE: Table, index, stored procedure, database, and view creation or alteration statements.
In InnoDB you have START TRANSACTION;, which in this engine is the officialy recommended way to do transactions, instead of SET AUTOCOMMIT = 0; (don't use SET AUTOCOMMIT = 0; for transactions in InnoDB unless it is for optimizing read only transactions). Commit with COMMIT;.
You might want to use SET AUTOCOMMIT = 0; in InnoDB for testing purposes, and not precisely for transactions.
In MyISAM you do not have START TRANSACTION;. In this engine, use SET AUTOCOMMIT = 0; for transactions. Commit with COMMIT; or SET AUTOCOMMIT = 1; (Difference explained in MyISAM example commentary below). You can do transactions this way in InnoDB too.
Source: http://dev.mysql.com/doc/refman/5.6/en/glossary.html#glos_autocommit
Examples of general use transactions:
/* InnoDB */
START TRANSACTION;
INSERT INTO table_name (table_field) VALUES ('foo');
INSERT INTO table_name (table_field) VALUES ('bar');
COMMIT; /* SET AUTOCOMMIT = 1 might not set AUTOCOMMIT to its previous state */
/* MyISAM */
SET AUTOCOMMIT = 0;
INSERT INTO table_name (table_field) VALUES ('foo');
INSERT INTO table_name (table_field) VALUES ('bar');
SET AUTOCOMMIT = 1; /* COMMIT statement instead would not restore AUTOCOMMIT to 1 */
https://dev.mysql.com/doc/refman/8.0/en/lock-tables.html
The correct way to use LOCK TABLES and UNLOCK TABLES with transactional tables, such as InnoDB tables, is to begin a transaction with SET autocommit = 0 (not START TRANSACTION) followed by LOCK TABLES, and to not call UNLOCK TABLES until you commit the transaction explicitly. For example, if you need to write to table t1 and read from table t2, you can do this:
SET autocommit=0;
LOCK TABLES t1 WRITE, t2 READ, ...;... do something with tables t1 and t2 here ...
COMMIT;
UNLOCK TABLES;
If you want to use rollback, then use start transaction and otherwise forget all those things,
By default, MySQL automatically commits the changes to the database.
To force MySQL not to commit these changes automatically, execute following:
SET autocommit = 0;
//OR
SET autocommit = OFF
To enable the autocommit mode explicitly:
SET autocommit = 1;
//OR
SET autocommit = ON;