MySQL死锁日志默认关闭,需设innodb_print_all_deadlocks=ON并确保MySQL对log_error路径有写权限,日志追加至错误日志文件,且受logrotate影响。

死锁日志默认不记录,必须手动开启
MySQL 默认不会把死锁信息写进日志,innodb_print_all_deadlocks 是个“关着的开关”,值为 OFF。你看到的错误日志里没有死锁详情,不是配置错了,而是它根本没开。
- 检查当前状态:
SHOW VARIABLES LIKE 'innodb_print_all_deadlocks';—— 如果返回OFF,就还没生效 - 临时开启(重启失效):
SET GLOBAL innodb_print_all_deadlocks = ON; - 永久生效:编辑
my.cnf或mysqld.cnf,在[mysqld]段落下加一行:innodb_print_all_deadlocks = 1 - 注意:该配置只影响新连接,已存在的连接不受影响
死锁日志实际输出到 MySQL 错误日志文件
开了 innodb_print_all_deadlocks 后,死锁事件不会单独生成一个“deadlock.log”,而是追加到 MySQL 的主错误日志里 —— 就是 log_error 配置指向的那个文件。
- 先确认路径:
SHOW VARIABLES LIKE 'log_error';,常见路径如/var/log/mysql/error.log或/usr/local/mysql/data/mysqld.local.err - 日志内容特征:每条死锁记录以
*** (1) TRANSACTION:和*** (2) TRANSACTION:开头,中间夹着锁等待链、SQL、索引、事务 ID 等关键信息 - 别用
tail -f直接盯错日志:要加--line-buffered参数,否则 grep 可能漏掉实时内容:tail -f /var/log/mysql/error.log | grep --line-buffered -i "deadlock"
SHOW ENGINE INNODB STATUS 只能看最近一次死锁
这个命令快、方便,但极其容易误导人——它只保留最后一次死锁的完整现场,之前发生的全被覆盖。线上偶发死锁,等你登录上去查时,大概率已经“没了”。
- 执行:
SHOW ENGINE INNODB STATUS\G,然后搜索LATEST DETECTED DEADLOCK区块 - 它不依赖配置,任何环境都能立刻用,适合应急初筛
- 但不能替代
innodb_print_all_deadlocks+ 错误日志方案:前者是“快照”,后者才是“录像带” - 注意:该命令输出量大,且含敏感信息(如 SQL 文本),生产环境慎用,尤其不要在未脱敏日志中长期留存
容易忽略的两个坑:权限与日志轮转
开了配置、改了路径,还是看不到死锁日志?大概率卡在这两个地方。
- MySQL 进程对日志路径**无写权限**:比如你配了
/var/log/mysql/deadlock.log,但 MySQL 用户(通常是mysql)没权限创建或写入该目录,日志就静默失败 —— 查error.log开头几行,常有Could not open log file提示 - 日志被自动轮转清空:很多系统用
logrotate每天切日志,如果没配置保留足够天数,上周的死锁记录可能已被删掉;建议在监控脚本里加时间戳归档,或用find /var/log/mysql -name "error.log.*" -mtime -7主动翻旧日志 - 另外,
innodb_print_all_deadlocks不影响性能,但错误日志体积会明显增大,尤其是高并发业务,需配合日志清理策略
死锁日志本身不难找,难点在于“找得全、留得住、读得懂”。很多人调通了 innodb_print_all_deadlocks 就以为万事大吉,结果线上又出问题,一查日志空空如也——往往不是配置没生效,而是日志路径不可写,或者轮转策略把证据删光了。


















