最准方法是查information_schema.innodb_trx表,重点关注trx_state(running或lock wait)、trx_started(越早越可疑)和trx_mysql_thread_id;需关联processlist定位来源,并检查autocommit设置与应用代码逻辑。

查活跃事务和长事务:INFORMATION_SCHEMA.INNODB_TRX
连接数爆满,往往不是连接本身没释放,而是事务卡住导致连接被长期占用。先确认是不是有事务没提交——直接查 INFORMATION_SCHEMA.INNODB_TRX 是最准的入口。
重点关注这几列:TRX_STATE(必须是 RUNNING 或 LOCK WAIT )、TRX_STARTED(时间越早越可疑)、TRX_MYSQL_THREAD_ID(对应 PROCESSLIST 的线程 ID)。
- 执行
SELECT TRX_ID, TRX_STATE, TRX_STARTED, TRX_MYSQL_THREAD_ID, TRX_QUERY FROM INFORMATION_SCHEMA.INNODB_TRX ORDER BY TRX_STARTED LIMIT 10; - 如果
TRX_STATE是RUNNING且TRX_STARTED超过几分钟,基本就是未提交事务;TRX_QUERY为空也不代表安全,可能是已执行完但没COMMIT或ROLLBACK - 注意:
TRX_STATE = LOCK WAIT时,说明它在等锁,背后可能有个更早的未提交事务在 hold 锁,得顺藤摸瓜找源头
关联线程状态和连接来源:INFORMATION_SCHEMA.PROCESSLIST
单看事务表不够,得知道这个事务是谁发起的、连的是哪个应用、有没有超时或异常行为。
用 TRX_MYSQL_THREAD_ID 去关联 INFORMATION_SCHEMA.PROCESSLIST,能拿到客户端 IP、用户、命令类型、运行时长、当前 SQL 等关键信息。
- 执行
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)) > 60); -
COMMAND是Sleep但TIME很大?十有八九是应用端开启事务后没处理完就挂了,或者代码里漏了commit/rollback -
HOST字段暴露客户端来源,比如app-server-03:54321,可快速定位到具体服务实例
检查 autocommit 设置和应用代码逻辑
很多“未提交”根本不是人为失误,而是 autocommit=0 模式下,应用误以为自己在自动提交,实际所有 DML 都在隐式事务里悬着。
- 查当前会话设置:
SELECT @@autocommit;—— 返回0就是手动事务模式 - 查全局默认:
SELECT @@global.autocommit;—— 如果是0,所有新连接默认都进手动事务,风险极高 - 常见坑:Java 的
DataSource配置了defaultAutoCommit=false,又没配@Transactional或没 catch 异常 rollback;Python 的pymysql默认autocommit=False,不显式conn.commit()就一直挂着 - 临时缓解可用
KILL,但必须同步排查代码:搜项目里所有BEGIN、START TRANSACTION、SET autocommit=0,确认每个分支都有对应COMMIT或ROLLBACK
预防性配置和监控建议
靠人工查太被动,得让系统自己“喊疼”。MySQL 本身不提供事务超时自动回滚,但可以通过组合配置降低风险。
- 设
innodb_lock_wait_timeout(默认 50 秒)—— 它只影响等锁超时,不影响事务空跑;真正管“事务最长存活时间”的是max_execution_time(仅对 SELECT 生效)或应用层控制 - 更有效的是启用
wait_timeout和interactive_timeout(建议设为 300–600),让空闲连接自动断开;但注意:这只能杀掉Sleep状态连接,对正在跑事务的无效 - 生产必须加监控项:定期查
SELECT COUNT(*) FROM INFORMATION_SCHEMA.INNODB_TRX WHERE TIME_TO_SEC(TIMEDIFF(NOW(), TRX_STARTED)) > 300;,超过阈值告警 - 别依赖
SHOW PROCESSLIST查长时间 Sleep 连接——它看不到事务状态,容易漏掉真正卡住的连接
事务没提交这事,表面是连接数高,根子常在应用代码里少了一行 commit 或异常路径没走 rollback。查的时候别只盯着连接数,重点盯 TRX_STARTED 和 TRX_STATE,再顺 HIST 找到对应应用实例,才能真正止血。











