启用 innodb_print_all_deadlocks = on 即可让每次死锁都写入错误日志,而不是只保留最近一次;mysql 5.7 默认仅在内存中缓存最后一次死锁详情,通过 show engine innodb status 仅能查看被覆盖的“latest detected deadlock”快照,无法追溯历史,需配置该参数并确保 log_error 路径可写,日志将追加至错误日志文件。

直接结论:启用 innodb_print_all_deadlocks = ON 即可让每次死锁都写入错误日志,而不是只保留最近一次。
为什么默认看不到所有死锁记录
MySQL 5.7 的 InnoDB 默认只在内存中缓存最后一次死锁详情,执行 SHOW ENGINE INNODB STATUS\G 只能查到“LATEST DETECTED DEADLOCK”段——它不持久、不归档、不自动落盘。线上出过三次死锁,你可能只看到最后一次,前两次完全丢失。
开启详细死锁日志的实操步骤
只需一个参数,但要注意生效范围和副作用:
- 临时开启(当前会话无效,必须 GLOBAL):
SET GLOBAL innodb_print_all_deadlocks = ON; - 永久生效:在
my.cnf的[mysqld]下添加innodb_print_all_deadlocks = ON,然后重启 MySQL - 验证是否生效:
SHOW VARIABLES LIKE 'innodb_print_all_deadlocks';—— 返回ON即成功 - 日志位置:死锁详情会追加到 MySQL 的
error log文件(路径由log_error变量指定,通常为/var/log/mysql/error.log或/data/mysql/error.log)
容易被忽略的关键细节
这个开关看似简单,但几个实际踩坑点必须注意:
- 它只影响“检测到的死锁”,不是所有锁等待;如果
innodb_deadlock_detect = OFF,就不会有死锁被检测到,自然也不会打印 - 日志内容包含事务 ID、SQL 语句、锁类型(Record Lock / Gap Lock)、等待图关系,但不会自动标注哪条 SQL 是罪魁祸首——得靠你比对
trx_wait_started和trx_started时间戳 - 开启后日志量会上升,尤其在高频死锁场景下,建议配合日志轮转(如 logrotate)避免填满磁盘
- 它不替代
SHOW ENGINE INNODB STATUS,后者仍是你排查“当前卡住状态”的第一入口;而innodb_print_all_deadlocks是事后归因的证据链
真正难的不是打开这个开关,而是从日志里还原出两个事务的加锁顺序——那才是死锁根源所在。











