Skip to main content

Which MySQL Statements Commit a Transaction Automatically

· 5 min read
Jagdish Kumawat
Founder @ Dewiride

Some MySQL statements can't run inside a transaction, so MySQL commits the transaction first and doesn't mention it. Your next ROLLBACK then has nothing to undo. It's why a failed migration can leave half its changes behind. Here's the behaviour, and the statements that cause it.

Prerequisites​

See It Happen​

The quantity starts at 50:

mysql
START TRANSACTION;
UPDATE products SET QuantityOnHand = 49 WHERE Id = 3;
CREATE TABLE notes (Id int PRIMARY KEY);
ROLLBACK;
SELECT Id, Sku, QuantityOnHand FROM products WHERE Id = 3;
Output (the SELECT)
+----+-------------+----------------+
| Id | Sku | QuantityOnHand |
+----+-------------+----------------+
| 3 | CBL-HDMI-2M | 49 |
+----+-------------+----------------+
1 row in set (0.001 sec)

A mysql session where an UPDATE to 49 is followed by CREATE TABLE and ROLLBACK, and a SELECT still shows 49.

49. The CREATE TABLE committed the UPDATE, and the ROLLBACK had nothing left to undo. No warning, and no error.

MySQL's implicit commit page says: "The statements listed in this section (and any synonyms for them) implicitly end any transaction active in the current session, as if you had done a COMMIT before executing the statement."

Which Statements Do It​

The page has the full list. These are the ones you're most likely to run:

KindStatements
Changing the structureCREATE TABLE, ALTER TABLE, DROP TABLE, TRUNCATE TABLE, RENAME TABLE, CREATE INDEX, DROP INDEX
Changing accountsCREATE USER, ALTER USER, DROP USER, GRANT, REVOKE
Transaction controlBEGIN, START TRANSACTION, SET autocommit = 1 when it was 0
LockingLOCK TABLES, and UNLOCK TABLES when tables are locked

It Commits Even If the Statement Fails​

This one I didn't expect. The table in this TRUNCATE doesn't exist:

mysql
START TRANSACTION;
UPDATE products SET QuantityOnHand = 49 WHERE Id = 3;
TRUNCATE TABLE __nosuchtable;
ROLLBACK;
SELECT Id, Sku, QuantityOnHand FROM products WHERE Id = 3;
Output (the TRUNCATE, then the SELECT)
ERROR 1146 (42S02): Table 'inventory.__nosuchtable' doesn't exist
+----+-------------+----------------+
| Id | Sku | QuantityOnHand |
+----+-------------+----------------+
| 3 | CBL-HDMI-2M | 49 |
+----+-------------+----------------+
1 row in set (0.001 sec)

The statement failed, and the UPDATE was committed all the same.

Temporary Tables Don't Commit​

CREATE TEMPORARY TABLE is the exception:

mysql
START TRANSACTION;
UPDATE products SET QuantityOnHand = 49 WHERE Id = 3;
CREATE TEMPORARY TABLE scratch (Id int PRIMARY KEY);
ROLLBACK;
SHOW WARNINGS;
SELECT Id, Sku, QuantityOnHand FROM products WHERE Id = 3;
Output (the warning, then the SELECT)
+---------+------+-----------------------------------------------------------------+
| Level | Code | Message |
+---------+------+-----------------------------------------------------------------+
| Warning | 1751 | The creation of some temporary tables could not be rolled back. |
+---------+------+-----------------------------------------------------------------+
1 row in set (0.000 sec)
+----+-------------+----------------+
| Id | Sku | QuantityOnHand |
+----+-------------+----------------+
| 3 | CBL-HDMI-2M | 50 |
+----+-------------+----------------+
1 row in set (0.001 sec)

The UPDATE was rolled back this time, and 50 is back. The temporary table stays, though, and that's what the warning is about: Fixed: Warning 1751.

Why This Matters for Migrations​

EF Core wraps each migration in START TRANSACTION and COMMIT, as How to Generate a SQL Script from EF Core Migrations shows. Most migrations are ALTER TABLE or CREATE TABLE, so each statement commits as it runs. If the third statement of a migration fails, the first two stay. Keep each migration small, and test it on a copy first.

Common Mistakes​

MistakeWhat happensDo this instead
Mixing ALTER TABLE with data changes in one transactionThe data changes are committed at the ALTERChange the structure separately
Expecting a failed DDL statement to leave the transaction openIt commits anywayFinish the transaction first
Relying on ROLLBACK to undo a migrationThe changes are already permanentWrite a way back, or test on a copy

Troubleshooting​

SymptomLikely causeFix
ROLLBACK didn't undo my changeA statement in between committedThe fix
A migration failed halfway, and left changes behindDDL commits as it goesRevert it, or fix it by hand
Warning 1751 after a ROLLBACKA temporary table can't be rolled backDrop the table yourself

Conclusion​

Statements that change the structure, change accounts or start a new transaction commit whatever you had open, even when they fail. Finish your transaction before running them, and don't count on ROLLBACK to undo a migration.

Additional Resources​

Stay Updated

Subscribe to our newsletter for the latest tutorials, tech insights, and developer news.

By subscribing, you agree to our privacy policy. Unsubscribe at any time.