优先用kill connection终止连接以释放锁并回滚事务,而非kill query(仅停语句但连接和锁仍存在);需先查innodb_trx与innodb_lock_waits定位持锁方,并核对线程状态、sql内容及归属再执行。

直接结论:别用 KILL QUERY,优先用 KILL CONNECTION(或简写 KILL)终止整个连接;但必须先确认线程状态、SQL内容和归属,否则可能中断正常业务。
怎么快速定位正在死锁的线程
死锁发生后,InnoDB 通常已自动回滚一个事务,但残留的锁或长事务仍会阻塞后续操作。不能只看 SHOW PROCESSLIST 里 State 是 Locked 就动手——那只是锁等待,不一定是死锁源头。
真正该查的是事务级视图:
- 执行
SELECT trx_id, trx_mysql_thread_id, trx_query, trx_state, trx_started FROM INFORMATION_SCHEMA.INNODB_TRX WHERE trx_state = 'LOCK WAIT',找出正在等锁的事务 - 再关联
INFORMATION_SCHEMA.INNODB_LOCK_WAITS查blocking_trx_id,它对应的trx_mysql_thread_id就是持锁方 - 如果查不到
LOCK WAIT状态,说明死锁已被自动处理,当前卡顿大概率是锁等待超时(Lock wait timeout exceeded)或元数据锁(MDL)阻塞
为什么必须用 KILL CONNECTION 而不是 KILL QUERY
KILL QUERY <code>thread_id 只终止当前语句,连接还活着,事务也未提交或回滚——这意味着锁依然持有。对死锁场景无效,甚至会让问题更隐蔽。
KILL CONNECTION <code>thread_id(MySQL 5.7+ 推荐写法,等价于旧版 KILL <code>thread_id)才会强制断开连接,触发事务回滚并释放所有锁。
- 执行后立刻跑
SHOW PROCESSLIST,确认该ID消失;若状态变成Killed却迟迟不退出,说明它在回滚大事务,只能等 - 注意:
KILL对SYSTEM USER线程(如复制 IO 线程)无效,也不能杀掉自己当前连接的thread_id - 误杀备份脚本、监控连接或长事务管理后台的线程,可能导致数据不一致或告警风暴
执行 KILL CONNECTION 前必须核对的三件事
别只看 trx_mysql_thread_id 数字就敲命令。真实线上环境里,90% 的“误杀”都源于没验证这三项:
- 线程是否还在活跃:查
SHOW PROCESSLIST,确认对应ID的State是Updating、Sending data或Locked,而不是Sleep - SQL 是否可安全中断:比如
UPDATE被 KILL 会回滚,但若事务已修改上万行,回滚本身要几十秒;而ALTER TABLE被杀可能留下临时表或元数据损坏 - 连接归属是否明确:检查
User和Host字段,排除 DBA 手动执行的诊断查询、备份工具(如 mydumper)、或应用健康检查连接
常见假死锁场景及对应处理方式
很多所谓“死锁”,其实是其他锁机制导致的阻塞,KILL CONNECTION 不仅无效,还可能恶化问题:
-
Waiting for table metadata lock:典型 DDL 阻塞,比如ALTER TABLE被一个慢SELECT卡住。该杀的是那个SELECT线程,不是ALTER发起者 -
trx_query为NULL:事务开了很久但没执行语句(如 START TRANSACTION 后挂起),得靠trx_started时间判断陈旧度,再结合SHOW PROCESSLIST的Time列交叉验证 - 应用报
Deadlock found when trying to get lock但INNODB_STATUS里没有新死锁记录:说明是历史死锁残留影响,重点查INNODB_TRX中trx_state = 'RUNNING'且trx_started异常早的事务
真正棘手的永远不是“怎么 kill”,而是“该不该 kill”——锁链式堵塞中,杀错一个节点,下游几十个等待事务全得重试。动手前多花 30 秒看 trx_query 内容和客户端 IP,比盲目执行 KILL 安全十倍。











