查活跃事务必须用information_schema.innodb_trx,因其稳定记录事务状态;trx_waiting_trx_id为空不等于无锁争用;监控应避免全表扫描、高频轮询,并结合threads、processlist_info等关联上下文识别问题事务。

查活跃事务必须用 information_schema.INNODB_TRX
MySQL 5.6+ 的活跃事务信息只稳定存在于 INNODB_TRX 表里,SHOW PROCESSLIST 只能看到连接和语句,看不到事务状态(比如是否加锁、是否在 sleep 状态但事务未提交)。误用 performance_schema.events_transactions_current 容易漏掉长事务——它默认不开启,且需手动配置 consumers 和 instruments。
实操建议:
- 直接查
SELECT * FROM information_schema.INNODB_TRX,重点关注TRX_STATE(RUNNING/LOCK WAIT)、TRX_STARTED(时间戳)、TRX_MYSQL_THREAD_ID(可关联PROCESSLIST) - 加
WHERE TRX_STATE = 'RUNNING' AND TIMESTAMPDIFF(SECOND, TRX_STARTED, NOW()) > 60快速揪出超 1 分钟的事务 - 别依赖
innodb_status输出——它只保留最近一次的摘要,无法做持续监控
TRX_WAITING_TRX_ID 字段为空不代表没锁争用
这个字段只在事务明确卡在行锁等待时才非空;但很多“伪活跃”事务(比如 autocommit=0 后执行了 SELECT 就停住)不会触发锁等待,TRX_WAITING_TRX_ID 仍是 NULL,却已持有锁、阻塞别人。这类事务在 INNODB_LOCK_WAITS 里也查不到,因为还没进入等待队列。
实操建议:
- 结合
INNODB_LOCKS和INNODB_TRX查持锁情况:SELECT t.TRX_ID, t.TRX_MYSQL_THREAD_ID, l.LOCK_TRX_ID, l.LOCK_MODE, l.LOCK_TYPE FROM information_schema.INNODB_TRX t JOIN information_schema.INNODB_LOCKS l ON t.TRX_ID = l.LOCK_TRX_ID - 注意
INNODB_LOCKS在 MySQL 8.0.1 中已被移除,改用performance_schema.data_locks,字段名和逻辑有差异(如LOCK_TRX_ID→ENGINE_TRANSACTION_ID) - 对疑似“静默持锁”的事务,用
SELECT * FROM performance_schema.threads WHERE THREAD_ID = ?查其PROCESSLIST_INFO,确认是否卡在空闲状态
监控脚本里别直接 SELECT * 扫全表
INNODB_TRX 是内存视图,每次查询都触发 InnoDB 内部遍历事务链表。在高并发写入场景下,频繁全扫会导致明显延迟,甚至拖慢正常事务提交。尤其当存在大量短事务时,TRX_ROWS_MODIFIED 字段计算开销也不小。
实操建议:
- 只查必要字段:
SELECT TRX_ID, TRX_MYSQL_THREAD_ID, TRX_STATE, TRX_STARTED, TRX_ROWS_MODIFIED, TRX_ISOLATION_LEVEL FROM information_schema.INNODB_TRX - 加
LIMIT防意外(如监控脚本误配成每秒执行):... LIMIT 100,超过 100 个活跃事务本身已是严重信号 - 避免在主库上高频轮询——考虑用
pt-heartbeat或导出到外部时序数据库聚合,而不是每 5 秒连一次 MySQL
MySQL 8.0 下 INNODB_TRX 的 TRX_OPERATION_STATE 值含义变具体了
8.0 新增该字段,值如 starting index read、updating foreign key constraints,比 5.7 的模糊状态更准。但要注意:它只反映事务当前所处的 InnoDB 层操作阶段,和 SQL 层语句无关;而且字段内容是内部字符串,官方不承诺兼容性,脚本里做字符串匹配要加容错(比如用 LIKE '%read%' 而非硬编码全匹配)。
实操建议:
- 优先用
TRX_STATE判断大类(ACTIVE/LOCK WAIT),再用TRX_OPERATION_STATE辅助定位瓶颈点 - 如果脚本需跨版本运行,先查
INFORMATION_SCHEMA.COLUMNS确认字段是否存在,再动态拼 SQL - 别拿这个字段做告警阈值——它的值变化极快,同一事务可能在毫秒级内切换多个状态
真正难的是区分“合理长事务”和“问题事务”:一个跑批的 UPDATE 占着事务两小时,和一个忘了 COMMIT 的交互式连接,监控指标看起来一样。得靠上下文——比如线程来源 IP、用户账号、PROCESSLIST_INFO 里的最后语句,这些信息必须和 INNODB_TRX 关联查,缺一不可。











