最准方法是查information_schema.innodb_trx表,重点关注trx_state='running'、trx_started时间早、trx_mysql_thread_id对应的连接状态,结合show full processlist确认是否真为未提交僵尸事务,再安全kill线程触发回滚。

查哪些事务卡住了没提交
直接看 information_schema.INNODB_TRX 表最准,它反映当前所有活跃的 InnoDB 事务真实状态。重点盯 TRX_STATE(必须是 RUNNING)、TRX_STARTED(时间戳越早越可疑)、TRX_MYSQL_THREAD_ID(对应连接 ID)这三列。
常用查询语句:
SELECT TRX_ID, TRX_MYSQL_THREAD_ID, TRX_STARTED, TRX_STATE, TRX_QUERY FROM information_schema.INNODB_TRX WHERE TRX_STATE = 'RUNNING' AND TIMESTAMPDIFF(SECOND, TRX_STARTED, NOW()) > 300;
这个 300 秒(5 分钟)是常见阈值,可根据业务容忍度调整。注意:只查 RUNNING 状态,LOCK WAIT 是等锁,不是“僵尸”;ROLLING BACK 是正在回滚,也不算未提交。
确认是不是真僵尸——别误杀活跃连接
拿到可疑的 TRX_MYSQL_THREAD_ID 后,不能直接 kill,先查它对应的连接在干嘛:
- 用
SHOW FULL PROCESSLIST查该线程的State和Info:如果State是Sleep且Info为空,大概率是应用没 commit/rollback 就断连了; - 如果
State是Query但Info显示的是SELECT或其他只读语句,说明事务里可能混了 DML 但没提交,得结合业务逻辑判断; - 检查
PROCESSLIST中的Time列(单位秒):如果远大于TRX_STARTED的持续时间,说明连接已空闲很久,事务却挂着不动。
安全终止事务:先 kill 连接,再等自动 rollback
MySQL 没有直接 “kill transaction” 的命令,只能 kill 对应连接。执行 KILL <code>TRX_MYSQL_THREAD_ID 后,事务会触发隐式 rollback,但 rollback 本身可能耗时——尤其涉及大量修改时。
关键点:
- 务必用
KILL <code>TRX_MYSQL_THREAD_ID,不是KILL QUERY <code>TRX_MYSQL_THREAD_ID(后者只中断当前语句,事务仍存在); - 执行后立刻查
INNODB_TRX,若该TRX_ID还在且TRX_STATE变成ROLLING BACK,说明 rollback 已启动,需等待完成; - 监控
INNODB_METRICS表里的innodb_trx_rollback_active计数器,或观察SHOW ENGINE INNODB STATUS中的 “ROLLING BACK” 进度条(如果有)。
预防比清理更重要:从应用和配置两头堵
频繁出现僵尸事务,说明应用层或服务端有隐患:
- 应用代码里每个
BEGIN必须配对COMMIT或ROLLBACK,尤其异常分支容易漏写; - 设置 MySQL 的
wait_timeout和interactive_timeout(建议 300–600 秒),让空闲连接自动断开,从而释放事务; - 开启
innodb_lock_wait_timeout(默认 50 秒)和max_execution_time(防长查询拖住事务),但注意后者不作用于事务内已执行的语句; - 避免在事务里做 RPC、文件读写、sleep 等阻塞操作——事务生命周期越长,变成僵尸的概率越高。
真正麻烦的不是 kill 命令怎么敲,而是 rollback 卡住时磁盘 I/O 拉满、其他事务全被堵死。所以查到僵尸事务后,第一反应不该是马上 kill,而是先看它改了多少行、有没有大事务痕迹。











