
为什么直接查 INFORMATION_SCHEMA.INNODB_TRX 会返回空?
MySQL 5.7 默认关闭了 innodb_status_output 和相关性能视图权限控制,但更常见的是:你没开启 innodb_stats_on_metadata 并不影响它——真正卡住的是权限和存储引擎状态本身。关键点是:INFORMATION_SCHEMA.INNODB_TRX 是实时内存快照,只显示当前活跃事务;如果没人在执行长事务、没锁等待、没未提交的 DML,它自然为空。
实操建议:
- 先确认你用的是
root或拥有PROCESS权限的账号(SELECT权限不够) - 执行
SHOW ENGINE INNODB STATUS\G,看输出里是否有TRANSACTIONS小节——这是交叉验证是否真有活跃事务的黄金标准 - 用
BEGIN; UPDATE t1 SET x=1 WHERE id=1;手动启一个不提交的事务,再查INNODB_TRX,就能看到数据了
INNODB_TRX 各字段怎么看才不误判?
这个表字段多,但真正影响排查的就几个。别被 TRX_STATE 的 “RUNNING” 迷惑——它只表示事务在执行中,不等于“正在做有用的事”。重点盯住:
-
TRX_STARTED:时间戳。超过 60 秒的事务大概率异常,结合业务逻辑判断是否该提交/回滚 -
TRX_WAITING_LOCK_ID:非 NULL 表示它正卡在等锁,此时必须配合INNODB_LOCK_WAITS查谁在阻塞它 -
TRX_ROWS_MODIFIED:大于 0 说明有未刷盘的变更,这类事务 crash 后可能触发回滚,影响恢复时间 -
TRX_ISOLATION_LEVEL:如果是REPEATABLE READ且持续很久,要警惕 MVCC 版本链过长拖慢查询
如何关联 INNODB_TRX、INNODB_LOCKS 和 INNODB_LOCK_WAITS 定位死锁源头?
MySQL 5.7 不像 8.0 那样把锁信息全塞进 performance_schema,所以这三张表是手动分析死锁链的唯一路径。注意:从 5.7.20 开始 INNODB_LOCKS 已被标记为 deprecated,但实际仍可用;若为空,优先查 performance_schema.data_locks(需开启 performance_schema 且配置正确)。
典型联查写法:
SELECT t1.TRX_ID waiting_trx_id, t1.TRX_QUERY waiting_query, t2.TRX_ID blocking_trx_id, t2.TRX_QUERY blocking_query FROM INFORMATION_SCHEMA.INNODB_TRX t1 INNER JOIN INFORMATION_SCHEMA.INNODB_LOCK_WAITS w ON t1.TRX_ID = w.BLOCKING_TRX_ID INNER JOIN INFORMATION_SCHEMA.INNODB_TRX t2 ON t2.TRX_ID = w.BLOCKED_TRX_ID;
注意坑点:
- 这个 SQL 只能查“当前正在等锁”的事务,刚发生的死锁会被自动 rollback,得靠错误日志里的
Deadlock found when trying to get lock记录反推 -
INNODB_LOCK_WAITS中的BLOCKING_TRX_ID和BLOCKED_TRX_ID是字符串,不是数字,JOIN 时类型要一致 - 如果
INNODB_LOCKS返回空,别硬查——检查是否设置了innodb_status_output = ON,或改用SELECT * FROM performance_schema.data_locks;
查 INNODB_TRX 影响性能吗?要不要加索引?
完全不用加索引,也加不了——INFORMATION_SCHEMA 下的表都是只读内存视图,底层没有物理表结构。但频繁轮询(比如每秒一次)会触发 InnoDB 内核反复采集事务状态,带来可观的 CPU 开销,尤其在高并发 OLTP 场景下。
生产建议:
- 监控类脚本拉取间隔 ≥ 10 秒;告警触发后才临时切到 1 秒粒度
- 避免在主库上长期运行
SELECT * FROM INNODB_TRX,改用带条件的轻量查询,例如:SELECT TRX_ID, TRX_STARTED, TRX_STATE FROM INNODB_TRX WHERE TRX_STARTED - 如果发现
TRX_STATE = 'LOCK WAIT'的记录持续存在,优先 kill 掉而不是继续观察——它大概率已卡死,不会自己恢复
最常被忽略的一点:事务 ID(TRX_ID)是递增整数,但重启 MySQL 后会重置。所以不能靠它跨实例比大小,也不能存下来当长期追踪依据。











