应查information_schema.innodb_trx中trx_state = 'ACTIVE'且trx_started超时的事务,而非仅看是否存在事务;开发阈值30秒、生产建议120秒起查,trx_query为空仍持锁占资源,需关联processlist定位静默挂起。

查 information_schema.innodb_trx 看 ACTIVE 且运行超时的事务
真正卡住日志增长和锁资源的,不是“有没有事务”,而是“开了多久还没提交”。innodb_trx 表里 trx_state = 'ACTIVE' 是核心筛选条件——它排除了已提交、回滚或 PREPARED 状态的事务。
重点看 trx_started 和当前时间的差值:
- 开发环境可设阈值为 30 秒
- 生产建议从 120 秒起查(避免误杀短时业务事务)
- 若 trx_query 为空,不代表没事:说明语句执行完了但没发 COMMIT,事务仍持锁、占 undo、拖 checkpoint
- 若 trx_query 非空,大概率是慢查询或锁等待卡住了
关联 information_schema.processlist 确认线程真实状态
SHOW PROCESSLIST 容易误判,因为它的 INFO 字段只显示“当前正在执行的语句”,事务空闲等待应用下发下一条命令时,INFO 就变 NULL,COMMAND 变成 Sleep,但事务还活着。
必须用 trx_mysql_thread_id 关联 processlist.id,重点关注:
- COMMAND 是 Sleep 但 TIME 很大 → 典型静默挂起
- USER 和 HOST 能快速定位是哪个应用实例连上来的
- DB 字段帮你确认是否影响关键库
- 不要依赖 TIME 判断事务时长——它只是线程空闲秒数,真正看 trx_started
警惕 ORM 自动管理失效导致的“静默挂起”
Django 的 @transaction.atomic、Spring 的 @Transactional 等机制,在抛异常时默认会回滚;但如果代码里 try...except 捕获了异常又没显式处理事务(比如忘了 rollback() 或没重新抛出),事务就会一直开着,而应用日志可能完全不报错。
这类事务在 innodb_trx 里表现为:
- trx_state = 'ACTIVE'
- trx_query = NULL
- trx_operation_state 常为 fetching rows 或空
- 对应的 processlist.COMMAND 是 Sleep,TIME 持续上涨
别只盯着 SHOW ENGINE INNODB STATUS 的 History list length
History list length 高确实是长事务的副作用之一,但它不是原因,而是结果。这个值上升可能由多种因素引起(如 purge 线程慢、大事务 rollback 中),单看它无法定位到具体哪个连接、哪条业务逻辑出了问题。
更危险的是:SHOW ENGINE INNODB STATUS 输出里事务列表只保留最近几百条,且不带线程 ID 映射,排查时容易漏掉低频但关键的长事务。实际应急时,优先跑这条 SQL:SELECT * FROM information_schema.innodb_trx WHERE trx_state = 'ACTIVE' AND trx_started
最常被忽略的一点:事务未提交隐患往往不出现在慢 SQL 报警里,而藏在 Sleep 状态的连接背后。一旦发现 trx_query 为空但 trx_started 很早,基本可以判定是应用端逻辑缺陷,不是数据库配置问题。


















