mysql存在“失效事务锁”需清理,因其innodb_lock_wait_timeout仅控制锁等待超时,不清理已卡死却未提交/回滚的悬挂事务,后者会长期持锁阻塞dml。

MySQL 为什么会有“失效事务锁”需要清理
MySQL 的 innodb_lock_wait_timeout 只控制等待锁的超时,不负责清理已卡死但未提交/回滚的事务。这类事务可能因应用崩溃、网络中断或程序逻辑 bug 导致长期持有锁却不释放,形成“悬挂事务”(zombie transaction),进而阻塞后续 DML。InnoDB 本身不会自动 kill 它们——得靠外部干预。
查出正在运行却疑似失效的事务
关键不是看“时间长”,而是看“没进展还占着锁”。用以下查询定位:
SELECT trx_id, trx_mysql_thread_id AS thread_id, trx_started, TIMEDIFF(NOW(), trx_started) AS duration, trx_state, trx_query FROM information_schema.INNODB_TRX WHERE trx_state = 'RUNNING' AND TIMEDIFF(NOW(), trx_started) > '00:10:00' AND trx_started <p>注意点:</p>
-
trx_state = 'RUNNING'不代表健康——它可能是 sleep 状态下拿着锁不动,比如应用开了事务但忘了 commit - 别只依赖
trx_started时间阈值,要结合业务场景判断:你的正常事务通常几秒?超过 2 分钟就值得怀疑 -
trx_query为空常见于空事务(BEGIN 后无操作),这种最危险:占锁、不干活、难察觉
用 SQL + 定时任务安全 kill 悬挂事务
不能直接在定时脚本里写 KILL,必须先确认、再执行、留日志。推荐用存储过程封装判断逻辑:
DELIMITER $$
CREATE PROCEDURE cleanup_zombie_trx()
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE v_trx_id VARCHAR(18);
DECLARE v_thread_id BIGINT;
DECLARE cur CURSOR FOR
SELECT trx_id, trx_mysql_thread_id
FROM information_schema.INNODB_TRX
WHERE trx_state = 'RUNNING'
AND trx_started OPEN cur;
read_loop: LOOP
FETCH cur INTO v_trx_id, v_thread_id;
IF done THEN
LEAVE read_loop;
END IF;
INSERT INTO cleanup_log VALUES (NOW(), v_thread_id, v_trx_id, 'killed');
KILL v_thread_id;
END LOOP;
CLOSE cur;
END$$
DELIMITER ;
调用方式:CALL cleanup_zombie_trx();
配套定时任务(Linux crontab):
*/5 * * * * mysql -uadmin -p'xxx' -e "CALL cleanup_zombie_trx();" >/dev/null 2>&1
要点:
- 别用
KILL QUERY—— 对持锁事务无效,必须用KILL(即KILL CONNECTION) - 权限要求:执行用户需有
SUPER或CONNECTION_ADMIN(MySQL 8.0+) - 日志表
cleanup_log必须提前建好,否则过程会静默失败 - 间隔设太短(如每分钟)易误杀正在慢跑的合法事务;建议从 5–10 分钟起步,观察后再调
比定时 kill 更稳的预防手段
定时清理是兜底,真正减少问题得从源头控住事务生命周期:
- 应用层务必设置
wait_timeout和interactive_timeout(建议 300 秒),避免连接空闲太久还挂着事务 - 所有事务块强制加超时控制:Java 用
@Transactional(timeout = 30),Go 用context.WithTimeout - 禁用 autocommit=0 的长连接直连模式;DBA 应在
my.cnf中显式配置autocommit=1 - 监控项必加:指标
INNODB_TRX.trx_state='RUNNING'的数量突增 + 持续时间分布,比单纯告警“锁等待超时”更有价值
真正麻烦的从来不是怎么 kill,而是你怎么确认它真的该被 kill——没有上下文的自动清理,和定时删生产库文件一样危险。











