Error
Error Code:
1205
MariaDB Error 1205: Lock Wait Timeout Exceeded
Description
This error occurs when a transaction in MariaDB attempts to acquire a lock on a database resource (like a row or table) but cannot obtain it within the configured `innodb_lock_wait_timeout` period. It typically indicates that another transaction is holding the required lock, preventing concurrent operations from proceeding.
Error Message
Lock wait timeout exceeded; try restarting transaction
Known Causes
4 known causesLong-Running Transactions
Transactions that perform extensive operations or are left open for too long can hold locks, blocking other transactions from accessing the same resources.
High Concurrency and Resource Contention
Multiple concurrent transactions attempting to modify the same rows or tables can lead to contention, where locks are frequently requested and held.
Inefficient Queries or Missing Indexes
Poorly optimized SQL queries without appropriate indexes can escalate lock granularity or scan more data, holding locks for longer durations than necessary.
Short Lock Wait Timeout Setting
The `innodb_lock_wait_timeout` variable might be set too low for the typical workload, causing transactions to time out prematurely under normal contention.
Solutions
5 solutions available1. Retry the Transaction easy
Simply retry as the error message suggests
1
Implement retry logic in your application
import time
import mysql.connector
def execute_with_retry(cursor, query, params, max_retries=3):
for attempt in range(max_retries):
try:
cursor.execute(query, params)
return cursor.fetchall()
except mysql.connector.Error as e:
if e.errno == 1205 and attempt < max_retries - 1:
time.sleep(1) # Wait before retry
continue
raise
2
PHP retry example
$maxRetries = 3;
for ($i = 0; $i < $maxRetries; $i++) {
try {
$pdo->beginTransaction();
// ... your queries ...
$pdo->commit();
break;
} catch (PDOException $e) {
$pdo->rollBack();
if (strpos($e->getMessage(), '1205') !== false && $i < $maxRetries - 1) {
sleep(1);
continue;
}
throw $e;
}
}
2. Find and Kill Blocking Transaction medium
Identify what's holding the lock
1
Find blocking transactions
SELECT * FROM information_schema.INNODB_LOCK_WAITS;
2
See all current locks
SELECT * FROM information_schema.INNODB_LOCKS;
3
Find long-running queries
SELECT * FROM information_schema.PROCESSLIST
WHERE TIME > 30
ORDER BY TIME DESC;
4
Kill blocking process if appropriate
KILL process_id;
3. Increase Lock Wait Timeout easy
Allow more time for locks to be released
1
Check current timeout setting (default is 50 seconds)
SHOW VARIABLES LIKE 'innodb_lock_wait_timeout';
2
Increase timeout for current session
SET innodb_lock_wait_timeout = 120;
3
Increase globally (persists until restart)
SET GLOBAL innodb_lock_wait_timeout = 120;
4
Make permanent in my.cnf
[mysqld]
innodb_lock_wait_timeout = 120
4. Optimize Queries and Add Indexes medium
Reduce lock duration by faster queries
1
Check if query is using indexes
EXPLAIN SELECT * FROM orders WHERE customer_id = 123;
2
Add index on frequently locked columns
CREATE INDEX idx_customer_id ON orders(customer_id);
3
Use SELECT FOR UPDATE only when needed
-- Avoid locking if you just need to read
-- Use normal SELECT instead of:
SELECT * FROM products WHERE id = 1 FOR UPDATE;
5. Reduce Transaction Scope medium
Keep transactions short to release locks faster
1
Break large transactions into smaller ones
-- Instead of one big transaction:
START TRANSACTION;
-- process 10000 rows
COMMIT;
-- Break into batches:
while rows_remaining:
START TRANSACTION;
-- process 100 rows
COMMIT;
2
Move non-critical operations outside transaction
-- Don't do this inside transaction:
START TRANSACTION;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
send_email_notification(); -- Slow, move outside!
COMMIT;
-- Better:
START TRANSACTION;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
COMMIT;
send_email_notification(); -- After commit
3
Commit frequently in batch operations
SET autocommit = 0;
DELETE FROM logs WHERE created_at < '2024-01-01' LIMIT 1000;
COMMIT;
DELETE FROM logs WHERE created_at < '2024-01-01' LIMIT 1000;
COMMIT;
-- Repeat until done