直接查 information_schema.innodb_trx 表即可判断是否存在活跃事务,该表仅记录已开始未提交或回滚的事务,有记录即说明存在未结束事务,需 process 权限。

怎么查当前有没有正在运行的事务
直接查 information_schema.INNODB_TRX 表就行,它只记录活跃事务(即已开始、尚未提交或回滚的事务)。只要表里有行,就说明存在未结束事务。
常见错误是去查 SHOW ENGINE INNODB STATUS,那输出太杂,且不便于脚本解析;还有人误以为查 information_schema.PROCESSLIST 就能覆盖所有事务——其实它只反映连接状态,跟事务生命周期不完全对齐。
-
SELECT * FROM information_schema.INNODB_TRX;最直接,字段如TRX_ID、TRX_STATE、TRX_STARTED都很关键 - 加
WHERE TRX_STATE = 'RUNNING'可过滤出真正卡住的事务(比如长时间没提交) - 注意权限:需要
PROCESS权限才能访问该表,否则会报错Access denied; you need (at least one of) the PROCESS privilege(s)
TRX_STATE 字段值到底代表什么
TRX_STATE 不是“成功/失败”二元状态,而是事务在 InnoDB 内部所处的生命周期阶段。最常看到的是 RUNNING、LOCK WAIT、ROLLING BACK,但它们含义容易被误解。
-
RUNNING:事务正在执行 SQL,不一定卡住,也可能只是还没到COMMIT这一步 -
LOCK WAIT:当前事务在等别的事务释放锁,这时候查TRX_WAITING_TRX_ID和TRX_MYSQL_THREAD_ID能定位阻塞源 -
ROLLING BACK:事务正在回滚,可能是手动ROLLBACK,也可能是崩溃恢复时自动触发 - 没有
COMMITTED或ABORTED状态——事务一旦提交或回滚,整条记录就从INNODB_TRX里消失了
为什么刚执行完 COMMIT,INNODB_TRX 里还能看到它
这不是数据延迟,而是事务可见性问题:InnoDB 的 MVCC 快照是在事务启动时确定的。如果你在另一个长事务里查 INNODB_TRX,可能仍能看到已被提交的事务 ID,因为它的快照没刷新。
- 典型场景:一个事务跑了 10 分钟,期间别人提交了 5 次,它查
INNODB_TRX仍可能显示那些已提交事务的残留信息 - 解决方法不是“刷新”,而是换连接查,或者用
SELECT * FROM information_schema.INNODB_TRX WHERE TRX_STARTED > NOW() - INTERVAL 1 SECOND;排除陈旧记录 - 注意:MySQL 8.0.13+ 加了
TRX_COMMITTED_BY_XID字段,可辅助判断是否已提交,但该字段只对显式 XA 事务有效,普通事务始终为NULL
想监控长期未提交事务,该怎么写告警 SQL
核心是结合时间判断和状态过滤,不能只看有没有记录,得看“活了多久”。重点防的是 RUNNING 状态超过阈值的事务,这类最容易演变成锁等待源头。
- 推荐语句:
SELECT TRX_ID, TRX_MYSQL_THREAD_ID, TRX_STARTED, NOW() - TRX_STARTED AS DURATION_SEC FROM information_schema.INNODB_TRX WHERE TRX_STATE = 'RUNNING' AND (NOW() - TRX_STARTED) > 60; - 别用
SLEEP()或轮询方式查,高并发下频繁扫INNODB_TRX本身会加重性能负担 - 生产环境建议把阈值设为 30 秒起步,低于这个值的“慢事务”大概率是正常业务逻辑,比如批量导入
- 如果发现大量
TRX_STATE = 'RUNNING'且TRX_OPERATION_STATE是starting index read,大概率是没加索引导致扫描卡住,得看执行计划
事务的“提交状态”本质上是瞬态信息,INNODB_TRX 只保留活着的痕迹。真正难的不是查出来,而是区分哪些是合理延迟、哪些是隐患信号——比如 TRX_STARTED 时间戳和应用日志对不上,或者同一 TRX_MYSQL_THREAD_ID 在不同时间反复出现在结果里,这种细节比单纯数行数重要得多。











