mysql死锁报错是其主动检测并终止冲突事务的正常行为,真正卡点是看不到死锁详情;需手动开启innodb_print_all_deadlocks(默认关闭),并确认错误日志路径及权限,否则日志不记录。

死锁报错本身不是 MySQL 的故障,而是它主动检测并终止了冲突事务的正常行为;你真正要解决的,是“看不到死锁详情”这个卡点——innodb_print_all_deadlocks 默认是关着的,不手动开,错误日志里就压根不会出现死锁记录。
怎么确认和开启 innodb_print_all_deadlocks
先查当前状态,别凭感觉假设它开了:
SHOW VARIABLES LIKE 'innodb_print_all_deadlocks';
如果返回 OFF,那就没生效。临时开(重启失效)用:
SET GLOBAL innodb_print_all_deadlocks = ON;
永久生效必须改配置文件,在 [mysqld] 段落加一行:
innodb_print_all_deadlocks = 1
注意:该设置只对新建立的连接生效,已连上的客户端不受影响;改完记得重启 MySQL 或 reload 配置(mysqladmin reload)。
死锁日志到底写到哪儿了
它不会新建文件,也不会写进 slow log 或 general log,只追加到 MySQL 的主错误日志里,路径由 log_error 变量决定:
SHOW VARIABLES LIKE 'log_error';
常见路径如 /var/log/mysql/error.log、/usr/local/mysql/data/mysqld.local.err。别直接 tail -f 就开 grep,得加 --line-buffered 否则实时内容可能被缓冲漏掉:
tail -f /var/log/mysql/error.log | grep --line-buffered -i "deadlock"
每条完整死锁记录以 *** (1) TRANSACTION: 和 *** (2) TRANSACTION: 开头,中间有 SQL、索引名、锁类型(X/S/GAP)、事务 ID 等关键信息。
为什么开了还是看不到死锁日志
- MySQL 进程对
log_error路径无写权限:比如目录属主是root,但 MySQL 以mysql用户运行,就会静默失败——去错误日志开头几行找Could not open log file类提示 - 日志被
logrotate清空了:很多系统每天轮转一次,且只保留 7 天;如果死锁发生在上周,现在去翻error.log就是空的;查/var/log/mysql/error.log.*压缩归档文件 - 误以为
SHOW ENGINE INNODB STATUS能替代它:这个命令只留最近一次死锁,线上偶发死锁时你登录上去大概率已经覆盖掉了,不能当证据链用
最常被忽略的一点:开了 innodb_print_all_deadlocks 后,日志里会出现大量重复或冗余的锁等待快照,尤其在高并发场景下;它不是为“实时监控”设计的,而是为“事后归因”服务的——所以分析时一定要结合时间戳、事务 ID 和具体 SQL,别被中间夹杂的无关锁信息带偏。











