Skip to main content

How to Check and Change the Transaction Isolation Level in MySQL

· 5 min read
Jagdish Kumawat
Founder @ Dewiride

An isolation level decides what a transaction can see of other transactions' work. MySQL has a default and three scopes to change it in, and the three statements look almost identical. This guide checks the current level and changes it at each scope, then proves which level a transaction really ran at.

Prerequisites​

The Four Levels​

MySQL's isolation levels page lists them: READ UNCOMMITTED, READ COMMITTED, REPEATABLE READ and SERIALIZABLE. It also says: "The default isolation level for InnoDB is REPEATABLE READ." READ COMMITTED vs REPEATABLE READ in MySQL shows the difference between the two you're most likely to use.

Step 1: Check the Current Level​

mysql
SELECT @@transaction_isolation, @@global.transaction_isolation;
Output
+-------------------------+--------------------------------+
| @@transaction_isolation | @@global.transaction_isolation |
+-------------------------+--------------------------------+
| REPEATABLE-READ | REPEATABLE-READ |
+-------------------------+--------------------------------+
1 row in set (0.000 sec)

The first column is your session. The second is the server's default, which new connections start with.

Step 2: Change It for This Session​

mysql
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
SELECT @@transaction_isolation, @@global.transaction_isolation;
Output (the SELECT)
+-------------------------+--------------------------------+
| @@transaction_isolation | @@global.transaction_isolation |
+-------------------------+--------------------------------+
| READ-COMMITTED | REPEATABLE-READ |
+-------------------------+--------------------------------+
1 row in set (0.000 sec)

Only this session changed, and it stays changed until you set it again or disconnect.

Step 3: Change It for the Next Transaction Only​

Without a scope word, the statement applies once. The SET TRANSACTION page says: "The statement applies only to the next single transaction performed within the session."

mysql
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SELECT @@transaction_isolation;
Output (the SELECT)
+-------------------------+
| @@transaction_isolation |
+-------------------------+
| READ-COMMITTED |
+-------------------------+
1 row in set (0.001 sec)

The variable still says READ-COMMITTED, so it can't tell you what's coming. To see what a transaction really runs at, start one and do some work in it:

mysql
START TRANSACTION;
SELECT COUNT(*) FROM products;

Then look from a root session:

mysql: root session
SELECT trx_mysql_thread_id, trx_isolation_level FROM information_schema.innodb_trx;
Output
+---------------------+---------------------+
| trx_mysql_thread_id | trx_isolation_level |
+---------------------+---------------------+
| 72 | SERIALIZABLE |
+---------------------+---------------------+
1 row in set (0.001 sec)

SERIALIZABLE, as asked. After COMMIT, the next transaction goes back to the session's level:

Output (the next transaction)
+---------------------+---------------------+
| trx_mysql_thread_id | trx_isolation_level |
+---------------------+---------------------+
| 72 | READ COMMITTED |
+---------------------+---------------------+
1 row in set (0.001 sec)

A root session reading information_schema.innodb_trx: the first transaction shows SERIALIZABLE and the next one shows READ COMMITTED.

Step 4: Change the Server's Default​

This needs an administrator:

mysql: root session
SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED;
SELECT @@global.transaction_isolation;
Output (the SELECT)
+--------------------------------+
| @@global.transaction_isolation |
+--------------------------------+
| READ-COMMITTED |
+--------------------------------+
1 row in set (0.001 sec)

It applies to connections made after this, and existing sessions keep what they have. A restart forgets it. To make it last, use the startup option the page names: "To set the server's default isolation level for all connections, use the --transaction-isolation option on the command line or in an option file."

Put it back to the default:

mysql: root session
SET GLOBAL TRANSACTION ISOLATION LEVEL REPEATABLE READ;

An ordinary account can't run this. It gets ERROR 1227.

Common Mistakes​

MistakeWhat happensDo this instead
Running SET TRANSACTION inside a transactionERROR 1568Run it before START TRANSACTION
Reading @@transaction_isolation to check a one-time levelIt shows the session's level, not the next transaction'sRead innodb_trx, as in Step 3
Leaving out SESSION and expecting it to lastIt applies to one transactionWrite SET SESSION
Expecting SET GLOBAL to change open sessionsThey keep their levelReconnect them

Troubleshooting​

SymptomLikely causeFix
Transaction characteristics can't be changed while a transaction is in progressA transaction is openCommit, then set it
Access denied; you need (at least one of) the SUPER or SYSTEM_VARIABLES_ADMINSET GLOBAL needs an administratorUse SET SESSION, or an admin account
The server is back at REPEATABLE READ after a restartSET GLOBAL doesn't survive oneUse the startup option
information_schema.innodb_trx is emptyThe transaction hasn't done any work yetRun a statement in it first

FAQ​

Which level should I use?​

The default suits most applications. READ COMMITTED sets fewer gap locks and each read sees fresh data, and some applications prefer it for that. READ COMMITTED vs REPEATABLE READ in MySQL shows both running.

Can I set it from .NET?​

Yes, per transaction: How to Set the Transaction Isolation Level in EF Core.

Conclusion​

@@transaction_isolation shows the session's level, and information_schema.innodb_trx shows what a transaction really runs at. No scope word means the next transaction, SESSION means this connection, and GLOBAL means new connections until the next restart.

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.