Skip to main content

How to Change the Lock Wait Timeout in MySQL

· 6 min read
Jagdish Kumawat
Founder @ Dewiride

A statement that can't get a row lock waits, and by default it waits 50 seconds. That's a long time for a web request to hang. innodb_lock_wait_timeout changes the limit, per session or for the whole server. And what happens when the limit passes isn't what most people expect.

Prerequisites​

Step 1: Check the Current Limit​

mysql: terminal 2
SELECT @@innodb_lock_wait_timeout, @@global.innodb_lock_wait_timeout, @@innodb_rollback_on_timeout;
Output
+----------------------------+-----------------------------------+------------------------------+
| @@innodb_lock_wait_timeout | @@global.innodb_lock_wait_timeout | @@innodb_rollback_on_timeout |
+----------------------------+-----------------------------------+------------------------------+
| 50 | 50 | 0 |
+----------------------------+-----------------------------------+------------------------------+
1 row in set (0.001 sec)

The first column is this session's limit, in seconds, and the second is what new connections start with. The InnoDB options page defines it as "The length of time in seconds an InnoDB transaction waits for a row lock before giving up."

Step 2: Change It for One Session​

mysql: terminal 2
SET SESSION innodb_lock_wait_timeout = 3;
SELECT @@innodb_lock_wait_timeout, @@global.innodb_lock_wait_timeout;
Output (the SELECT)
+----------------------------+-----------------------------------+
| @@innodb_lock_wait_timeout | @@global.innodb_lock_wait_timeout |
+----------------------------+-----------------------------------+
| 3 | 50 |
+----------------------------+-----------------------------------+
1 row in set (0.000 sec)

This needs no special rights, and it's how an application sets its own limit: How to Set a Lock Wait Timeout from EF Core does it from .NET.

Step 3: Watch It Give Up​

The first terminal holds a row:

mysql: terminal 1
START TRANSACTION;
UPDATE products SET QuantityOnHand = 49 WHERE Id = 3;

The second wants it:

mysql: terminal 2
UPDATE products SET QuantityOnHand = 48 WHERE Id = 3;

Three seconds later:

Output
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

Step 4: See What the Timeout Undid​

This is the part to remember. Do it again, this time with another change earlier in the transaction:

mysql: terminal 2
START TRANSACTION;
UPDATE products SET QuantityOnHand = 47 WHERE Id = 4;
UPDATE products SET QuantityOnHand = 48 WHERE Id = 3;
Output (the last statement)
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

The transaction is still open, and the first change is still in it:

mysql: terminal 2
SELECT Id, QuantityOnHand FROM products WHERE Id IN (3, 4);
Output
+----+----------------+
| Id | QuantityOnHand |
+----+----------------+
| 3 | 50 |
| 4 | 47 |
+----+----------------+
2 rows in set (0.001 sec)

A transaction where an UPDATE fails with ERROR 1205 Lock wait timeout exceeded, and a SELECT afterwards shows the earlier change to product 4, at 47, still in place.

The error handling page says: "A lock wait timeout causes InnoDB to roll back the current statement (the statement that was waiting for the lock and encountered the timeout)." So a COMMIT here would save half the work. Run ROLLBACK yourself:

mysql: terminal 2
ROLLBACK;
SELECT Id, QuantityOnHand FROM products WHERE Id IN (3, 4);
Output (the SELECT)
+----+----------------+
| Id | QuantityOnHand |
+----+----------------+
| 3 | 50 |
| 4 | 50 |
+----+----------------+
2 rows in set (0.001 sec)

There is a setting that makes a timeout roll back the whole transaction, innodb_rollback_on_timeout, but it can only be set when the server starts. Trying at runtime gets ERROR 1238.

Step 5: Change It for New Connections​

An administrator can change what new connections start with:

mysql: root session
SET GLOBAL innodb_lock_wait_timeout = 10;
SELECT @@global.innodb_lock_wait_timeout, @@innodb_lock_wait_timeout;
Output (the SELECT)
+-----------------------------------+----------------------------+
| @@global.innodb_lock_wait_timeout | @@innodb_lock_wait_timeout |
+-----------------------------------+----------------------------+
| 10 | 50 |
+-----------------------------------+----------------------------+
1 row in set (0.001 sec)

Your own session still shows 50, and only new connections get 10. Put it back with the same statement. An ordinary account gets ERROR 1227.

What the Limit Covers​

The page is specific: "innodb_lock_wait_timeout applies to InnoDB row locks." It doesn't cover the waiting an ALTER TABLE does for a metadata lock, and deadlocks don't wait for it at all: "The lock wait timeout value does not apply to deadlocks when innodb_deadlock_detect is enabled (the default) because InnoDB detects deadlocks immediately and rolls back one of the deadlocked transactions."

Common Mistakes​

MistakeWhat happensDo this instead
Committing after a 1205The statements before it are savedROLLBACK, then try again
Treating it like a deadlockA deadlock rolls back everything, and a timeout only the statementHandle them separately
Raising the limit to make the error go awayRequests hang for longerFind what's holding the lock
Setting SET GLOBAL and expecting your session to changeYour session keeps its valueReconnect, or use SET SESSION

Troubleshooting​

SymptomLikely causeFix
Lock wait timeout exceeded; try restarting transactionAnother transaction held the row for too longThe fix
The limit is back to 50 after a restartSET GLOBAL doesn't lastUse --innodb-lock-wait-timeout at startup
A statement waits past the limitIt's waiting on something other than a row lockCheck for a metadata lock

FAQ​

What's a good value?​

For a web API, a few seconds. The person waiting for a page won't wait 50 seconds, so it's better to fail sooner and say so. The product in this series uses 5.

Conclusion​

SET SESSION innodb_lock_wait_timeout = 3 is all an application needs. When the limit passes, only the waiting statement is undone, and the transaction stays open with everything before it, so roll it back yourself.

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.