information_schema.innodb_trx是唯一实时查看未提交/未回滚innodb事务的系统表,需结合processlist和performance_schema.data_lock_waits定位阻塞源头与会话详情。

INFORMATION_SCHEMA.INNODB_TRX 是唯一能实时查到“正在运行的事务”的途径,其他命令(如 SHOW PROCESSLIST 或 SHOW ENGINE INNODB STATUS)只能辅助定位,不能替代它。
查当前活跃事务必须用 INNODB_TRX
MySQL 没有 SHOW CURRENT TRANSACTION 这种命令。所有“当前事务”都指尚未提交或回滚的 InnoDB 事务,而 INFORMATION_SCHEMA.INNODB_TRX 是唯一结构化、实时反映这些事务的系统表。
-
TRX_STATE = 'RUNNING'表示事务正常执行中;若TRX_STARTED时间远早于现在(比如超 60 秒),大概率是应用漏了COMMIT或ROLLBACK -
TRX_STATE = 'LOCK WAIT'表示该事务卡在锁上,但表里不直接告诉你谁在持锁——必须继续查performance_schema.data_lock_waits -
TRX_QUERY是 VARCHAR(1024),超长会被截断;为空很常见:刚BEGIN、刚执行完UPDATE正等下一条、或只做了SELECT FOR UPDATE就停住 - MyISAM 表操作、已提交/已回滚的事务、
autocommit=1下单条语句都不出现在这个表里
关联 PROCESSLIST 才知道是谁连的、从哪来的
单看 INNODB_TRX 只知道事务状态,不知道连接来源。必须用 TRX_MYSQL_THREAD_ID 去关联 information_schema.PROCESSLIST:
- 执行
SELECT p.ID, p.USER, p.HOST, p.DB, p.COMMAND, p.TIME, p.STATE, p.INFO FROM information_schema.PROCESSLIST p JOIN information_schema.INNODB_TRX t ON p.ID = t.trx_mysql_thread_id WHERE t.trx_state = 'LOCK WAIT'; -
COMMAND = 'Sleep'且TIME > 300,基本确定是应用拿了连接没释放,事务挂着不动 -
STATE = 'Locked'或'Updating'且TIME持续上涨,说明 SQL 本身可能卡在 I/O 或锁等待,不是代码逻辑问题 -
INFO字段可能为空——尤其用了预处理(如 PDO 设置PDO::ATTR_EMULATE_PREPARES = true)时,真实 SQL 不在这里
MySQL 8.0+ 查阻塞源头得用 performance_schema.data_lock_waits
老文档里常提的 INNODB_LOCK_WAITS 在 MySQL 8.0+ 已移除,硬套会查不到数据。正确路径是:
-
SELECT * FROM performance_schema.data_lock_waits;直接给出等待链:REQUESTING_ENGINE_TRANSACTION_ID(等锁方)、BLOCKING_ENGINE_TRANSACTION_ID(持锁方) - 再用这两个 ID 去查
performance_schema.data_locks,确认锁类型(RECORD还是TABLE)、锁模式(X还是S)、锁在哪张表哪个索引上 - 注意:从库上
data_lock_waits大概率为空——因为 SQL 线程以autocommit=1回放,事务瞬时提交,几乎不持锁
别忽略 @@in_transaction 和 @@autocommit
这两个会话级变量能快速判断当前连接是否“逻辑上”处于事务中:
-
SELECT @@in_transaction;返回1表示当前会话确实在一个未结束的事务里(MySQL 5.6+ 支持) -
SELECT @@autocommit;返回0才可能累积多条语句进同一事务;返回1时每条语句都是独立短事务,INNODB_TRX里基本看不到它 - 组合执行
SELECT CONNECTION_ID(), @@autocommit, @@in_transaction;是日常调试第一句,比盲目扫全表快得多
真正卡住的事务往往不在你预期的位置:可能是凌晨跑批脚本忘了 COMMIT,也可能是监控探针连上来只 BEGIN 不操作,还可能是从库上根本查不到——因为它的“事务”是按秒粒度回放的,不是你在主库看到的那种长生命周期对象。











