Home > Enterprise >  Deadlocks - At what point are locks acquired in a transaction?
Deadlocks - At what point are locks acquired in a transaction?

Time:01-15

animals table

 ---------- ------- 
| name     | value |
 ---------- ------- 
| Aardvark |    10 |
 ---------- ------- 

birds table

 --------- ------- 
| name    | value |
 --------- ------- 
| Buzzard |    20 |
 --------- ------- 

Session 1:

mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT value FROM Animals WHERE name='Aardvark' FOR SHARE;
 ------- 
| value |
 ------- 
|    10 |
 ------- 
1 row in set (0.00 sec)

Session 2:

mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT value FROM Birds WHERE name='Buzzard' FOR SHARE;
 ------- 
| value |
 ------- 
|    20 |
 ------- 
1 row in set (0.00 sec)

--waits to lock
mysql> UPDATE Animals SET value=30 WHERE name='Aardvark';

Session 1:

mysql> UPDATE Birds SET value=40 WHERE name='Buzzard';
ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction

Can we say that the lock is acquired UNTIL THE SQL SENTENCE IS REACHED or does a transaction obtain all locks before?

A lot of people say that we have to acquire all the (anticipated) locks that we are going to use throughout the transaction to avoid deadlocks, so the question arose in my mind.

CodePudding user response:

Yes, row locks are acquired on demand, when you execute the SQL statement that requires those locks.

This means that if two sessions are running concurrently, they may acquire their respective locks in an interleaved fashion, not an atomic fashion. Therefore they might both want to lock a resource that is already locked by the other session, and in that case they create a deadlock.

One fix to prevent deadlocks is to acquire all the locks you need during the transaction — and more to the point, acquire the locks atomically. That is, all the locks must be acquired at once, and if that isn't successful, then release all the locks. Locks cannot be acquired in an interleaved fashion.

InnoDB doesn't really have a feature to do this. You may resort to table locking with MySQL's LOCK TABLES statement.

A different strategy is not to avoid deadlocks, but just recover from deadlocks when they occur.

  • Related