死锁可通过报错“Deadlock found when trying to get lock”确认,而“Lock wait timeout exceeded”是锁等待超时;用SHOW ENGINE INNODB STATUS\G查LATEST DETECTED DEADLOCK定位回滚事务;MySQL 8.0+应查performance_schema.data_locks和sys.innodb_lock_waits分析锁关系;KILL前须验证blocking_pid来源,避免误杀system user或event_scheduler线程。

怎么看是不是死锁,而不是锁等待超时
看到报错里明确写着 Deadlock found when trying to get lock,就是死锁;如果报的是 Lock wait timeout exceeded,那就不是死锁,是事务等锁太久被 MySQL 主动放弃——这种情况下 KILL 报错线程没用,得找真正持锁的线程。
查最近一次死锁详情用 SHOW ENGINE INNODB STATUS\G
这条命令输出里翻到 LATEST DETECTED DEADLOCK 区块,它会告诉你:
- 两个(或多个)事务各自的
trx_id和mysql_thread_id - 每个事务正在执行的 SQL(
query id后面那句) - 谁在等什么锁(
WAITING FOR THIS LOCK TO BE GRANTED) - 谁持有哪个锁(
HOLDS THE LOCK(S)) - 最关键的一行:
*** WE ROLL BACK TRANSACTION (1)—— MySQL 已经自动回滚了编号为 (1) 的那个事务,你不用再手动干预它
MySQL 8.0+ 查实时锁等待关系用 performance_schema.data_locks 和 sys.innodb_lock_waits
老版本的 INNODB_LOCKS 和 INNODB_LOCK_WAITS 在 MySQL 8.0+ 已废弃,直接查这两个:
-
SELECT * FROM performance_schema.data_locks;—— 看当前所有锁的类型、表、索引、事务 ID -
SELECT * FROM sys.innodb_lock_waits;—— 字段更友好,含waiting_pid和blocking_pid,一眼能定位谁卡着谁 - 注意:
sys库默认启用,但若被禁用过,需确认sys.schema_auto_increment_columns是否可查,否则视图可能为空
KILL 前先确认线程身份,别误杀 system user 或主从同步线程
拿到 blocking_pid 后,别急着 KILL,先查它的来源:
SELECT ID, USER, HOST, COMMAND, TIME, STATE, INFO FROM information_schema.PROCESSLIST WHERE ID = ?;- 重点看
USER列:system user是主从 IO/SQL 线程,KILL 会导致复制中断;event_scheduler是定时任务,KILL 会跳过本次调度 - 再看
STATE:如果是Rolling back,说明它已经在回滚,KILL 不会加速,反而可能延长清理时间 - 真正该 KILL 的,是那些
State = 'Sleep'且Time很大(比如 > 60)、INFO为空的线程——大概率是应用端没 commit/rollback 就断连了,锁还挂着
死锁本身由 InnoDB 自动处理,你不需要“解决死锁”,只需要防止它反复发生。最容易被忽略的点是:应用层重试逻辑若没做幂等,被自动回滚的事务重放后,可能立刻再次触发相同死锁路径。


















