MySQL 中的死锁:engine.log 分析

Kse*_*nia 4 mysql deadlock

如何理解死锁的原因——即如何找出哪些事务捕获了哪些锁?

我有带有以下死锁的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)
Run Code Online (Sandbox Code Playgroud)

我对日志中描述的内容的看法如下:

1. Transaction ?2 最初有一个锁(并且从日志中没有明确锁的类型):

*** (2) 锁住锁

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

记录锁,堆没有 27 物理记录:n_fields 72;紧凑的格式;信息位 0

2.事务?1试图获取S类型的锁:

*** (1) 等待这个锁定被授予:

RECORD LOCKS ... trx id 4 2719072253 锁定模式 S 锁定记录但不是间隙等待

在尝试失败后,它开始等待释放事务 ?2 锁;

3.然后事务?2试图获取X类型的锁:

*** (2) 等待这个锁定被授予:

RECORD LOCKS ... trx id 4 2719072205 lock_mode X 锁定记录但不是间隙等待

在尝试失败后,它开始等待,直到事务 ?1 获得 S 锁并释放它。

我是否正确理解日志,还是我的解释错误?

Sha*_*dow 6

你的解释几乎是正确的。补充几点想法:

  • 在 innodb 中有两种基本类型的锁:共享(S)和排他(X)。如果一个事务在一条记录上持有 X 锁,那么在事务完成之前,不能对相同的记录授予 S 或 X 锁。如果一个事务在一条记录上持有 S 锁,则可以立即授予另一个 S 锁,但 X 锁请求必须等到第一个事务完成。

  • 第二个事务是update对正在更新的索引记录持有排他 (X) 锁。因此,第一个事务无法在相同的记录上获得 S 锁。但是,第二个事务正在等待在不同的记录集上授予 X 锁(page no与其他锁不同)。

  • 摘录没有告诉我们哪个事务锁定了第二个事务正在等待的记录。我们只能假设它是第一笔交易——否则不会出现死锁。