应查innodb_trx定位持锁事务,kill connection强制回滚释放锁,警惕mdl锁及伪僵死会话,勿依赖wait_timeout,需应用层超时控制与人工复核。

查 INNODB_TRX 找出真正持锁的活跃事务
别只看 SHOW PROCESSLIST 里状态是 Sleep 就跳过——僵死连接往往表现为 Command = Sleep 但 trx_state = RUNNING 或 LOCK WAIT,说明事务没提交也没回滚,锁还挂着。
执行以下查询定位:
SELECT trx_id, trx_mysql_thread_id, trx_query, trx_state, trx_started, trx_rows_locked
FROM INFORMATION_SCHEMA.INNODB_TRX
WHERE trx_state IN ('RUNNING', 'LOCK WAIT') AND trx_started
<p>重点看 <code>trx_query</code> 是否为空(空表示事务卡在中间)、<code>trx_rows_locked</code> 是否异常高(比如上万行),以及 <code>trx_started</code> 时间是否远超业务预期。</p>
<h3>KILL CONNECTION 而不是 KILL QUERY</h3>
<p><code>KILL QUERY <code>thread_id</code></code> 只停当前语句,连接不断,事务不回滚,锁照常持有——对僵死连接完全无效,甚至会让锁等待链更难排查。<br><code>KILL CONNECTION <code>thread_id</code></code>(MySQL 5.7+ 推荐写法,等价于旧版 <code>KILL <code>thread_id</code></code>)才会强制断连、触发事务回滚、释放所有锁。</p>
- 执行后立刻查
SHOW PROCESSLIST,确认该ID消失;若状态变成Killed却卡住,说明正在回滚大事务,只能等 - 别对
User = 'system user'(如复制线程)或你自己的当前连接执行KILL - 注意权限:需
PROCESS+SUPER(5.7+ 还要CONNECTION_ADMIN)
警惕 MDL 锁和伪僵死会话
有些“卡住”根本不是事务锁,而是元数据锁(Waiting for table metadata lock),常见于 DDL 操作被未提交事务阻塞。这类锁不会出现在 INNODB_TRX,得查:
SELECT blocking_pid, object_schema, object_name, operation FROM performance_schema.metadata_locks WHERE owner_thread_id IN ( SELECT thread_id FROM performance_schema.threads WHERE processlist_command = 'Sleep' ) AND lock_status = 'PENDING';
如果发现 blocking_pid 对应一个长时间 Sleep 的连接,它大概率就是源头——但不能直接 KILL,先查它的 INFO 字段确认是否为业务事务,否则可能中断备份或监控。
自动清理不等于可靠,别依赖 wait_timeout
wait_timeout 和 interactive_timeout 只对 Command = Sleep 且无活跃事务的连接生效,对已启动事务但卡住的连接完全无效。默认 28800 秒(8 小时)在生产环境基本形同虚设。
真正有效的做法是:
- 应用层设置合理的事务超时(如 JDBC 的
queryTimeout) - DBA 定期跑脚本识别并人工复核
TIME > 300且STATE IN ('Locked', 'Waiting for table metadata lock')的连接 - 避免在事务里做 RPC 调用、文件读写、sleep 等外部耗时操作
最危险的不是锁本身,而是你以为它已被释放——比如 KILL CONNECTION 后看到进程消失就以为完事了,其实回滚还没结束,锁仍在释放途中。盯住 INNODB_TRX 和 SHOW ENGINE INNODB STATUS 里的 TRANSACTIONS 部分,直到确认对应 trx_id 彻底消失。











