死锁日志需重点分析两个事务块,通过TRANSACTION ID、ACTIVE时间、HOLDS/WAITING锁及末尾SQL定位冲突环路与业务缺陷,并用SHOW ENGINE INNODB STATUS、innodb_print_all_deadlocks或information_schema表主动捕获。

死锁日志里找关键事务对
死锁日志本质是两个(或多个)事务互相卡住的“快照”,重点看带 *** (1) TRANSACTION 和 *** (2) TRANSACTION 的两段。它们构成一个闭环:A等B的锁,B又等A的锁。
注意每段开头的 TRANSACTION ID(如 TRANSACTION 10047),这是唯一标识;再看 ACTIVE X sec,时间越短的通常是后发起、被回滚的那个(MySQL默认回滚代价小的事务)。
锁定资源和等待关系要对照着读
每个事务块里有三类关键行:
-
HOLDS THE LOCK(S):它现在攥着什么锁(比如
RECORD LOCKS space id 44 page no 3 index PRIMARY) -
WAITING FOR THIS LOCK:它正伸手要哪个锁(比如
lock_mode X locks rec but not gap waiting) - query id xxx ... updating / deleting ...:最后执行的那条SQL,就是冲突源头
把事务1的 WAITING 和事务2的 HOLDS 对上,事务2的 WAITING 和事务1的 HOLDS 对上,就串出了死锁环路。例如:
事务1 → 等 idx_account 锁 → 该锁被事务2持有
事务2 → 等 PRIMARY 锁 → 该锁被事务1持有
从SQL语句反推业务逻辑缺陷
日志末尾的 SQL 往往很短,但必须结合表结构和索引理解实际加锁范围:
-
UPDATE t1 SET x=1 WHERE i = 1→ 若i是普通索引,会先持i索引上的记录锁,再持主键上的记录锁 -
DELETE FROM t1 WHERE mobile='185...'→ 若mobile有唯一索引,只锁匹配行;若非唯一,则可能触发间隙锁(lock_mode X locks gap before rec) -
INSERT ... ON DUPLICATE KEY UPDATE→ 在重复键检查阶段可能同时申请主键+唯一索引的锁,顺序不一致易引发死锁
快速定位死锁日志的三种方式
不是每次都能等到日志自动打印,得主动抓取:
- 用
SHOW ENGINE INNODB STATUS\G查最近一次死锁(仅保留最后一次,适合应急) - 开启持久化记录:
SET GLOBAL innodb_print_all_deadlocks = ON,之后所有死锁写入错误日志,可按时间检索 - 查系统表辅助验证:
SELECT * FROM information_schema.INNODB_TRX看当前运行事务,INNODB_LOCK_WAITS看谁在等谁










