必须先查INNODB_TRX定位真实事务,再按状态选KILL CONNECTION或KILL QUERY;只看SHOW PROCESSLIST会漏掉90%持锁长事务,真正卡住的是TRX_STATE='RUNNING'且TRX_QUERY IS NULL、运行超30秒的Sleep连接。

必须先查 INNODB_TRX 定位真实事务,再按状态选 KILL CONNECTION 或跳过误杀;只看 SHOW PROCESSLIST 会漏掉 90% 的持锁长事务,且盲目 KILL 可能引发回滚风暴、IO 雪崩或主从断裂。
怎么查到真正卡住的长事务(不是Sleep假空闲)
别信 SHOW PROCESSLIST 的 Time 字段——它只算当前语句执行时长,而真正钉死锁和 undo 的,是那些 Command = 'Sleep'、State IS NULL、但 TRX_STATE = 'RUNNING' 且 TRX_QUERY IS NULL 的连接。
- 执行查询定位:
SELECT trx_id, trx_mysql_thread_id AS thread_id, trx_started, TIMESTAMPDIFF(SECOND, trx_started, NOW()) AS duration_sec, trx_state, trx_rows_modified FROM information_schema.INNODB_TRX WHERE TIMESTAMPDIFF(SECOND, trx_started, NOW()) > 30 AND trx_state = 'RUNNING' ORDER BY trx_started LIMIT 5;
- 重点关注:
duration_sec > 30、trx_state = 'RUNNING'、trx_query IS NULL—— 这类极大概率是应用崩溃后连接未关闭,或 ORM 忘记commit/rollback - 若
trx_rows_modified > 10000且duration_sec > 300,需立刻干预;回滚可能耗时数分钟,不是命令没生效,而是正在后台滚动 - 用
trx_mysql_thread_id关联information_schema.PROCESSLIST确认HANDLER、USER、HOST,排除定时任务、DBA 工具(如 DBeaver)等合理长连接
该用 KILL QUERY 还是 KILL CONNECTION(MySQL 5.7+)
KILL QUERY 只中断当前语句,事务仍存活;KILL CONNECTION 才真正终止事务并触发回滚——但必须分场景,否则适得其反。
- 适用
KILL CONNECTION <code>thread_id:TRX_STATE = 'RUNNING'且TRX_QUERY IS NULL(空转事务)、或State是Sleep但已挂住数分钟 - 适用
KILL QUERY <code>thread_id:线程State = 'Query'且INFO显示正在跑慢SELECT或UPDATE,且你希望复用连接(如连接池场景) - 严禁对
TRX_WAITING_TRX_ID IS NOT NULL(即等待锁的事务)执行KILL CONNECTION:这会让上游持锁者继续跑,下游堵得更死 - 严禁对
TRX_STATE = 'ROLLING BACK'再次KILL:此时回滚已在异步进行,重复KILL不加速,反而可能中断清理流程
KILL 后锁还没释放?不是失败,是回滚太重
SHOW PROCESSLIST 显示状态为 Killed 是正常现象,不代表事务已结束。InnoDB 回滚耗时通常是正向操作的 3–5 倍,尤其当 trx_rows_modified 较大时。
- 查
INNODB_TRX中该事务的TRX_OPERATION_STATE是否为rolling back,确认是否真在回滚中 - 观察
TRX_ROWS_MODIFIED估算剩余工作量:百万行修改可能卡在Rolling back状态 2–5 分钟 - 若
History list length在SHOW ENGINE INNODB STATUS\G中长期不降,说明 purge 被阻塞——必须先杀掉源头事务,再调大innodb_purge_batch_size - 杀完后务必验证:再次查
INNODB_TRX,结果为空才算真正退出;仅看PROCESSLIST是否消失不可靠,因为线程 ID 可能被复用
为什么不能写脚本批量 KILL(哪怕加了 sleep)
人工轮询 + KILL 脚本看似高效,实则风险集中:刚查完事务就提交了,KILL 却误杀;拼接用户输入有 SQL 注入隐患;KILL 后未检查是否真退出,下次又重复执行。
- 更稳妥的是用
pt-kill --busy-time 30 --match-command Query --victim all --kill:它内置竞争规避、连接重试、日志审计,还能用--print先预演 - 生产环境建议加权限过滤:只查
trx_isolation_level = 'REPEATABLE-READ'且非root用户的连接,降低误操作概率 - 最易被忽略的一点:
KILL后必须立刻查INNODB_TRX和INNODB_METRICS中的innodb_trx_rollback_active计数器,而不是只盯PROCESSLIST


















