MySQL 中的死锁:engine.log 分析
Deadlock in MySQL: engine.log analyze
如何理解死锁的原因——即如何找出哪些事务捕获了哪些锁?
我的 engine.log 文件有以下死锁:
------------------------
LATEST DETECTED DEADLOCK
------------------------
170327 11:09:53
*** (1) TRANSACTION:
TRANSACTION 4 2719072253, ACTIVE 5 sec, OS thread id 26215 starting index read
...
INSERT INTO... (the first transaction)
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 0 page no 36025889 n bits 96 index `PRIMARY` of table `mydb`.`mytable` trx id 4 2719072253 lock mode S locks rec but not gap waiting
...
*** (2) TRANSACTION:
TRANSACTION 4 2719072205, ACTIVE 35 sec, OS thread id 25564 starting index read, thread declared inside InnoDB 485
UPDATE ... (the second transaction)
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 0 page no 36025889 n bits 96 index `PRIMARY` of table `mydb`.`mytable` trx id 4 2719072205 lock_mode X locks rec but not gap
Record lock, heap no 27 PHYSICAL RECORD: n_fields 72; compact format; info bits 0
...
*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 0 page no 42767646 n bits 120 index `PRIMARY` of table `mydb`.`mytable` trx id 4 2719072205 lock_mode X locks rec but not gap waiting
...
*** WE ROLL BACK TRANSACTION (1)
我对日志中描述的内容的看法如下:
1. Transaction №2 最初有一个锁(锁的类型从日志中不清楚):
*** (2) HOLDS THE LOCK(S)
RECORD LOCKS space id 0 page no 36025889 n bits 96 index PRIMARY of
table mydb.mytable trx id 4 2719072205 lock_mode X locks rec but not
gap
Record lock, heap no 27 PHYSICAL RECORD: n_fields 72; compact format;
info bits 0
2. 交易 #1 正在尝试获取 S 类型的锁:
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS ... trx id 4 2719072253 lock mode S locks rec but not gap
waiting
尝试失败后开始等待释放事务№2锁;
3. 那么事务 #2 正在尝试获取 X 类型的锁:
*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS ... trx id 4 2719072205 lock_mode X locks rec but not gap
waiting
在尝试不成功后,它开始等待,直到事务 1 获得 S 锁并释放它。
我对日志的理解是正确的,还是我的理解有误?
您的解释几乎是正确的。补充几点:
在innodb中有two basic types of locks:共享(S)和独占(X)。如果事务在记录上持有 X 锁,则在事务完成之前,不能对同一记录授予 S 锁或 X 锁。如果一个事务持有记录上的 S 锁,那么可以立即授予另一个 S 锁,但是 X 锁请求必须等到第一个事务完成。
作为 update
的第二个事务对正在更新的索引记录持有独占 (X) 锁。因此,第一个事务无法在相同的记录上获得 S 锁。但是,第二个事务正在等待在不同的记录集上授予 X 锁(page no
与其他锁不同)。
摘录并没有告诉我们什么事务锁定了第二个事务正在等待的记录。我们只能假设这是第一笔交易——否则就不会是死锁。
如何理解死锁的原因——即如何找出哪些事务捕获了哪些锁?
我的 engine.log 文件有以下死锁:
------------------------
LATEST DETECTED DEADLOCK
------------------------
170327 11:09:53
*** (1) TRANSACTION:
TRANSACTION 4 2719072253, ACTIVE 5 sec, OS thread id 26215 starting index read
...
INSERT INTO... (the first transaction)
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 0 page no 36025889 n bits 96 index `PRIMARY` of table `mydb`.`mytable` trx id 4 2719072253 lock mode S locks rec but not gap waiting
...
*** (2) TRANSACTION:
TRANSACTION 4 2719072205, ACTIVE 35 sec, OS thread id 25564 starting index read, thread declared inside InnoDB 485
UPDATE ... (the second transaction)
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 0 page no 36025889 n bits 96 index `PRIMARY` of table `mydb`.`mytable` trx id 4 2719072205 lock_mode X locks rec but not gap
Record lock, heap no 27 PHYSICAL RECORD: n_fields 72; compact format; info bits 0
...
*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 0 page no 42767646 n bits 120 index `PRIMARY` of table `mydb`.`mytable` trx id 4 2719072205 lock_mode X locks rec but not gap waiting
...
*** WE ROLL BACK TRANSACTION (1)
我对日志中描述的内容的看法如下:
1. Transaction №2 最初有一个锁(锁的类型从日志中不清楚):
*** (2) HOLDS THE LOCK(S)
RECORD LOCKS space id 0 page no 36025889 n bits 96 index PRIMARY of table mydb.mytable trx id 4 2719072205 lock_mode X locks rec but not gap
Record lock, heap no 27 PHYSICAL RECORD: n_fields 72; compact format; info bits 0
2. 交易 #1 正在尝试获取 S 类型的锁:
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS ... trx id 4 2719072253 lock mode S locks rec but not gap waiting
尝试失败后开始等待释放事务№2锁;
3. 那么事务 #2 正在尝试获取 X 类型的锁:
*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS ... trx id 4 2719072205 lock_mode X locks rec but not gap waiting
在尝试不成功后,它开始等待,直到事务 1 获得 S 锁并释放它。
我对日志的理解是正确的,还是我的理解有误?
您的解释几乎是正确的。补充几点:
在innodb中有two basic types of locks:共享(S)和独占(X)。如果事务在记录上持有 X 锁,则在事务完成之前,不能对同一记录授予 S 锁或 X 锁。如果一个事务持有记录上的 S 锁,那么可以立即授予另一个 S 锁,但是 X 锁请求必须等到第一个事务完成。
作为
update
的第二个事务对正在更新的索引记录持有独占 (X) 锁。因此,第一个事务无法在相同的记录上获得 S 锁。但是,第二个事务正在等待在不同的记录集上授予 X 锁(page no
与其他锁不同)。摘录并没有告诉我们什么事务锁定了第二个事务正在等待的记录。我们只能假设这是第一笔交易——否则就不会是死锁。