查不到持锁事务主因是权限不足或账号受限,需用root或具备process+select权限账号;innodb_trx不显示只读事务及autocommit=1的单条语句,应结合trx_started判断长事务,生产建议阈值设为30秒。

查不到持锁事务?先确认权限和表访问路径
直接执行 SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX 返回空,不等于没长事务——大概率是权限不足或用了普通账号。必须用 root 或具备 PROCESS 和 SELECT 权限的账号登录;否则连 INFORMATION_SCHEMA.PROCESSLIST 都看不到全貌。另外,INNODB_TRX 不收录只读事务、已提交但未释放间隙锁的事务,也不含 autocommit=1 下的单条语句。重点盯 TRX_STARTED 和当前时间差,生产环境建议阈值设为 30 秒而非 10 分钟,早发现早干预。
KILL TRANSACTION 还是 KILL CONNECTION?看 MySQL 版本和锁类型
MySQL 5.7+ 支持 KILL TRANSACTION <code>TRX_ID,它只终止事务本身,连接保活,适合连接池场景;5.6 及更早版本只能退而求其次用 KILL QUERY <code>ID,但它不结束事务,TRX_STATE 仍为 RUNNING 或 LOCK WAIT,锁不会释放。严禁用 KILL <code>ID(即 KILL CONNECTION)去杀等待方——这会让持锁者继续跑,其他请求照堵。正确顺序是:从 INNODB_LOCK_WAITS 找出 BLOCKING_TRX_ID → 关联 INNODB_TRX 拿到对应 TRX_MYSQL_THREAD_ID → 再 KILL TRANSACTION 或 KILL QUERY。
KILL 之后锁还在?不是命令失败,是回滚没完
执行 KILL 后 SHOW PROCESSLIST 显示状态为 Killed 是正常现象,不代表锁已释放。InnoDB 必须按 undo log 逆向回滚,耗时 ≈ 正向操作的 3~5 倍。小事务(几行更新)通常 100ms 内完成;大事务(如百万行 UPDATE)可能卡在 Rolling back 状态数分钟。此时锁仍被占用,新请求继续排队。若发现 kill 后锁“一直不放”,先查 INNODB_TRX 中该事务的 TRX_OPERATION_STATE 是否为 rolling back,再看 TRX_ROWS_MODIFIED 估算剩余工作量。
为什么不能跳过排查直接批量 KILL?
手动写脚本轮询 INNODB_TRX + KILL 看似高效,实际风险集中:并发下可能刚查完就提交了,KILL 却误杀;脚本若拼接用户输入,有 SQL 注入隐患;KILL 后未检查是否真退出,下次又重复执行。更稳妥的是用 pt-kill --busy-time 30 --match-command Query --victim all --kill,它内置竞争规避、连接重试、日志审计,还能配合 --print 先预演。人工干预前,务必先用 SELECT * FROM performance_schema.threads WHERE PROCESSLIST_ID = ? 查出对应应用用户和 SQL,留痕备查。











