应查innodb_trx表,重点关注trx_state为running或lock wait、trx_started早于当前时间超300秒、trx_mysql_thread_id可关联processlist的事务;trx_query为空不表示安全,可能dml已执行但未提交;需结合autocommit设置与连接池配置综合判断。

查 INFORMATION_SCHEMA.INNODB_TRX 看事务状态和启动时间
真正卡住连接的,往往不是连接本身没断,而是事务一直没提交或回滚。直接查 INFORMATION_SCHEMA.INNODB_TRX 是最准的起点。
重点关注三列:TRX_STATE(必须是 RUNNING 或 LOCK WAIT)、TRX_STARTED(越早越危险)、TRX_MYSQL_THREAD_ID(后续要关联来源)。
执行这条语句快速筛出可疑长事务:
SELECT TRX_ID, TRX_STATE, TRX_STARTED, TRX_MYSQL_THREAD_ID, TRX_QUERY
FROM INFORMATION_SCHEMA.INNODB_TRX
WHERE TRX_STATE IN ('RUNNING', 'LOCK WAIT')
AND TIME_TO_SEC(TIMEDIFF(NOW(), TRX_STARTED)) > 300;
-
TRX_QUERY为空 ≠ 安全:可能是 DML 执行完但没COMMIT或ROLLBACK -
TRX_STATE = LOCK WAIT时,它只是“表象”,背后大概率有个更早的RUNNING事务在 hold 锁,得顺TRX_MYSQL_THREAD_ID往回追 - 别只看 5 分钟阈值——业务场景不同,有的系统容忍 30 秒,有的能接受 2 分钟;按实际 SLA 调整
> 300这个值
用 TRX_MYSQL_THREAD_ID 关联 PROCESSLIST 定位客户端
光知道事务 ID 没用,得知道是谁连的、从哪来的、干了啥。用 TRX_MYSQL_THREAD_ID 去关联 INFORMATION_SCHEMA.PROCESSLIST,就能拿到真实上下文。
执行:
SELECT ID, USER, HOST, COMMAND, TIME, STATE, INFO
FROM INFORMATION_SCHEMA.PROCESSLIST
WHERE ID IN (
SELECT TRX_MYSQL_THREAD_ID
FROM INFORMATION_SCHEMA.INNODB_TRX
WHERE TRX_STATE = 'RUNNING'
AND TIME_TO_SEC(TIMEDIFF(NOW(), TRX_STARTED)) > 300
);
-
COMMAND = Sleep但TIME很大(比如 1800+)?基本可断定应用端开了事务后挂了、异常退出、或代码漏了commit/rollback -
HOST字段很关键:像app-order-02:52143这种带端口的,能直接定位到具体 Pod 或机器 -
INFO为空但STATE是executing或updating?说明 SQL 正在跑,不是泄漏,是真慢——得另查执行计划
检查 autocommit 设置是否被全局关闭
很多“未提交”根本不是疏忽,而是整个 MySQL 实例或会话默认关了自动提交,导致所有 DML 都悬在隐式事务里。
先查当前会话设置:
SELECT @@autocommit;
再查全局默认:
SELECT @@global.autocommit;
- 返回
0就是手动事务模式,风险极高 - Java 应用常见坑:
DataSource配了defaultAutoCommit=false,又没加@Transactional或没在 catch 块里rollback() - Python 的
pymysql或mysql-connector-python默认也是autocommit=False,必须显式设autocommit=True或手动commit()
别忽略 wait_timeout 和连接池 idle 配置错位
MySQL 不会主动杀掉 Sleep 连接,除非超时。而这个超时值(wait_timeout)和应用层连接池的空闲回收策略一旦不匹配,就会掩盖泄漏问题。
-
wait_timeout默认是 28800 秒(8 小时),线上建议设为300(5 分钟)并动态生效:SET GLOBAL wait_timeout = 300; - 但注意:该设置只对新连接生效,已存在的 Sleep 连接仍按旧值计时
- HikariCP 必须同步调低:
idle-timeout(建议 ≤ 240 秒)、max-lifetime(建议 ≤ 1800 秒),否则连接池以为连接还健康,MySQL 却已悄悄断开,下次复用就报Connection reset
真正的难点不在发现,而在确认——事务是卡在应用逻辑里没走完,还是网络中断后连接僵死却没被清理;这两类问题的修复路径完全不同,得靠 PROCESSLIST 的 STATE 和应用日志交叉验证。











