innodb_deadlock_detect不是频率控制器,而是开关型参数,仅支持ON/OFF;死锁检测在每次加锁失败瞬间实时触发wait-for graph判定,毫秒级完成,无“检测间隔”概念。

innodb_deadlock_detect 不是频率控制器,它没有“检测频率”可配。
MySQL 8.0 的死锁检测不是定时轮询,而是在**每次加锁失败、进入等待状态的瞬间实时触发**。所谓“每秒检查一次”是误传——实际由锁等待事件驱动:事务一阻塞,就立刻构建 wait-for graph 并判定环路,整个过程在毫秒级完成。
为什么找不到 innodb_deadlock_detect_interval 这个参数?
这个参数根本不存在于 MySQL 8.0+ 的源码和文档中。网上出现的 innodb_deadlock_detect_interval=5 是混淆了旧版本(如 Percona 分支)或错误配置项的写法。官方 MySQL 8.0 只有 innodb_deadlock_detect,且仅接受 ON 或 OFF 两种值。
死锁处理权重由什么决定?
InnoDB 回滚哪个事务,取决于“事务代价”(transaction weight),主要依据以下两个指标(按优先级):
- 修改的行数(rows modified)越少,越可能被选为牺牲者
- 事务持有的锁数量(number of locks held)越少,权重越低
注意:innodb_rollback_on_timeout 默认是 OFF,它控制的是锁超时(ERROR 1205)是否回滚整个事务,与死锁回滚(ERROR 1213)无关。
你真正能调的三个关键参数
别在“检测频率”上浪费时间,这三个才是高频、有效、必须关注的:
-
innodb_lock_wait_timeout:设为5或10(单位秒),防止长等待拖垮连接池;仅对当前会话生效更安全:SET SESSION innodb_lock_wait_timeout = 5; -
innodb_print_all_deadlocks:设为ON(MySQL 8.0.22+ 支持动态设置),确保每次死锁都落盘到 error log,否则只保留最近一次 -
innodb_deadlock_detect:保持默认ON;仅当满足「所有事务严格同序访问表 + CPU 已严重瓶颈」时才考虑关,关掉后SHOW ENGINE INNODB STATUS中的LATEST DETECTED DEADLOCK段将消失
查死锁到底卡在哪?别看错地方
执行 SHOW ENGINE INNODB STATUS\G 后,只盯紧 LATEST DETECTED DEADLOCK 区块。重点比对:
- 两个事务各自的
HELD LOCKS(持有锁的索引、记录位置) - 各自
WAITING FOR THIS LOCK TO BE GRANTED(等待谁、等哪条记录) - SQL 语句是否用了不同索引(比如一个走
PRIMARY,另一个走idx_user_id)
如果反复出现相同表+不同索引路径,说明应用层没统一访问顺序,参数再怎么调也白搭。
真正难的从来不是配参数,而是从LATEST DETECTED DEADLOCK 日志里看出两个事务是怎么绕成圈的——那几行 SQL 和锁记录,就是唯一真相。


















