mysql死锁检测不会引发连锁反应,仅回滚一个事务并释放其全部锁;所谓连锁反应实为误操作(如手动kill、关闭死锁检测或长事务残留)导致的二次阻塞。

MySQL 本身不会因死锁检测引发“连锁反应”——它只回滚一个事务,且立即释放其全部锁;所谓“连锁反应”,其实是误操作(如手动 KILL、关闭死锁检测、或长事务残留)导致的二次阻塞。
为什么 KILL 死锁事务反而会让系统更卡?
死锁发生后,InnoDB 已经自动回滚了代价小的事务(比如 TRANSACTION 123456),并抛出 Deadlock found when trying to get lock; try restarting transaction。此时若你看到 SHOW PROCESSLIST 里还有个状态为 Locked 或 Waiting for table flush 的线程,大概率不是死锁残留,而是:
- 该线程正执行
FLUSH TABLES WITH READ LOCK(常见于误用mysqldump --lock-tables) - 它本身是长事务(
INNODB_TRX中trx_started时间很早),持有行锁未释放,其他事务在等它 - 你试图
KILL的是正在执行UPDATE的业务线程,而不是死锁中已被回滚的那个——KILL 后触发大范围回滚,反而加剧锁等待
SHOW ENGINE INNODB STATUS 里 “LATEST DETECTED DEADLOCK” 看什么?
这段日志不是用来“找要杀的线程”的,而是唯一能确认死锁根因的依据。重点关注三块:
-
*** (1) TRANSACTION:和*** (2) TRANSACTION:—— 两个真实参与死锁的事务 ID(注意不是PROCESSLIST中的ID) -
*** (1) HOLDS THE LOCK(S):和*** (2) WAITING FOR THIS LOCK TO BE GRANTED:—— 明确写出谁持有什么锁、在等什么锁,比如space id 100 page no 10 ... lock_mode X locks rec but not gap -
WE ROLL BACK TRANSACTION (1)—— MySQL 已选中回滚哪个事务,无需你干预
如果日志里没有 WE ROLL BACK 行,说明 innodb_deadlock_detect=OFF 被关了,这不是死锁处理问题,是配置错误,必须立刻修复。
真正需要人工终止的场景只有两种
这两种情况都和“死锁检测”无关,而是外部干扰或配置失当:
-
mysqldump 卡在 FTWRL 阶段:执行
SHOW PROCESSLIST找到State = Waiting for table flush且Info含FLUSH TABLES WITH READ LOCK的线程,KILL它可解除全局读锁,但备份文件不完整,需重跑 -
长事务持续阻塞:查
SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX WHERE TIME_TO_SEC(NOW() - trx_started) > 60,找出运行超 1 分钟的事务,再结合trx_mysql_thread_id去PROCESSLIST确认是否异常,仅在此类情况下才考虑KILL
最常被忽略的一点:innodb_lock_wait_timeout 设置再高,也救不了死锁——它只管“等锁超时”,不管“循环等待”。死锁检测是独立机制,关了它等于把数据库交给运气。











