SHOW ENGINE INNODB STATUS是排查MySQL死锁最直接命令,其输出中仅“LATEST DETECTED DEADLOCK”区块关键,包含两个事务的WAITING FOR THIS LOCK、HOLDS THE LOCK(S)及WE ROLL BACK TRANSACTION信息,需对照分析;它仅保留最近一次死锁,高频场景须配合innodb_print_all_deadlocks=ON落盘日志。

SHOW ENGINE INNODB STATUS 是排查 MySQL 死锁最直接、最常用的命令,但它输出内容多且杂,不加筛选容易漏掉关键信息。执行后若没看到 LATEST DETECTED DEADLOCK 区块,不代表没发生死锁——可能已被自动回滚,也可能日志未开启全量记录。
怎么看懂 SHOW ENGINE INNODB STATUS\G 的死锁片段
输出中真正有用的只有 LATEST DETECTED DEADLOCK 下面那一段,其他全是干扰项。它通常包含两个事务(TRANSACTION 1 和 TRANSACTION 2),每段里有三类关键字段:
-
WAITING FOR THIS LOCK:当前事务卡在哪条 SQL、等哪个索引、哪一行(会显示主键值或间隙范围) -
HOLDS THE LOCK(S):它自己已经持有哪些锁(注意是否是间隙锁lock_mode X locks gap before rec) -
WE ROLL BACK TRANSACTION (1):MySQL 自动选了哪个事务做牺牲者(通常是 undo log 小的那个)
常见误区是只看 WAITING 部分,却忽略 HOLDS ——死锁本质是“你等我手里的,我也等你手里的”,必须对照着看。
为什么 SHOW ENGINE INNODB STATUS 只显示最后一次死锁
MySQL 默认只保留最近一次死锁的完整现场,历史记录会被覆盖。这意味着:
- 如果业务高频死锁,
SHOW ENGINE INNODB STATUS每次执行都可能只看到最新的一次,旧的全丢了 - 线上监控不能依赖它实时抓取,必须配合日志落盘
- MySQL 8.0.24+ 才支持
innodb_print_all_deadlocks = ON,老版本只能靠错误日志 + 定期轮询
启用方式分两步:SET GLOBAL innodb_print_all_deadlocks = ON(临时),再在 my.cnf 中加 innodb_print_all_deadlocks = 1(永久)。注意:该配置只影响 error log,不影响 SHOW ENGINE INNODB STATUS 的输出内容。
死锁日志里看到 lock_mode X locks gap before rec 怎么办
这表示事务在非唯一索引上加了间隙锁(gap lock),不是行锁。典型触发场景:
- WHERE 条件用了普通索引(如
name = 'Alice'),但name没建唯一约束 - 执行的是
SELECT ... FOR UPDATE或更新语句,InnoDB 为防止幻读会锁住间隙 - 两个事务同时对同一间隙加锁,就可能互相等待
解决方向不是删索引,而是:
- 确认业务是否真需要可重复读隔离级别;如不需要,降级到
READ COMMITTED可禁用间隙锁(但要评估一致性风险) - 给查询字段加唯一索引(让 gap lock 退化为 record lock)
- 避免在事务中先查后更,改用带条件的原子更新,比如
UPDATE t SET balance = balance - 10 WHERE id = ? AND balance >= 10
用 information_schema.INNODB_TRX 辅助定位活跃事务
SHOW ENGINE INNODB STATUS 是快照,而 INNODB_TRX 是实时视图,适合发现“正在等锁但还没形成死锁”的长事务:
-
trx_state = 'LOCK WAIT'表示该事务正卡在锁上(可能是死锁前兆) -
trx_started和trx_wait_started时间差过大,说明锁等待太久,需人工干预 - 结合
trx_mysql_thread_id可快速 kill 掉问题线程:KILL [thread_id]
注意:INNODB_TRX 不显示锁的具体对象,必须和 performance_schema.data_locks(MySQL 8.0+)联查才能知道它到底在等哪一行——这点很多人忽略,结果只看到“在等锁”,却不知道等谁。
真正难的不是看到死锁,而是从 WAITING FOR THIS LOCK 和 HOLDS THE LOCK(S) 的两段 SQL 里,反推出 Java 代码里事务的执行顺序和加锁路径。这个映射过程没有自动工具,得人工比对。











