只查innodb_trx不够用,因它仅显示事务状态而无等待关系;需联动processlist确认会话来源,并结合performance_schema.data_lock_waits定位阻塞源。

直接查 information_schema.INNODB_TRX 是唯一能实时看到“谁卡着没提交”的方式,但单看它容易误判——必须联动 PROCESSLIST 和 performance_schema.data_lock_waits 才能定位真正阻塞源。
为什么只查 INNODB_TRX 不够用
这张表只告诉你“有事务在跑”,不告诉你“谁在等谁”。比如 trx_state = 'LOCK WAIT' 的行,你看到的是等待方,但表里没有字段直接指出持锁的是谁;trx_query 为空也很常见——事务刚 BEGIN、或只执行了 SELECT ... FOR UPDATE 就停住,后续没发语句,那字段就是 NULL;trx_id 是 InnoDB 内部 ID,不能直接 KILL,真正能操作的是 trx_mysql_thread_id。
怎么用 INNODB_TRX 快速筛出可疑事务
重点关注这几个组合条件:
-
trx_state = 'RUNNING'且trx_started :大概率是应用漏了 <code>COMMIT或ROLLBACK,不是 SQL 慢,是事务挂死了 -
trx_state = 'LOCK WAIT'且trx_wait_started时间持续增长:说明它卡在锁上,得立刻查谁在挡路 -
trx_weight值异常高(比如 >10000):通常意味着事务改/锁了大量行,可能是大更新或未加 LIMIT 的 DELETE
示例查询:
SELECT trx_id, trx_state, trx_started, trx_wait_started, trx_weight, trx_mysql_thread_id, trx_query
FROM information_schema.INNODB_TRX
WHERE trx_state IN ('RUNNING', 'LOCK WAIT')
AND (trx_started <h3>必须关联 <code>PROCESSLIST</code> 看真实会话</h3><p><code>trx_mysql_thread_id</code> 是桥梁,拿它去匹配 <code>information_schema.PROCESSLIST</code> 才知道这个事务是谁连的、从哪来的、现在在干啥:</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill2334" title="MySQL"><img
src="https://img.php.cn/upload/skill/000/000/081/178900927846657.jpg" alt="MySQL" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/skill2334" title="MySQL" class="overflowclass">MySQL</a>
<p class="overflowclass">编写正确的MySQL查询,避免字符集、索引和锁方面的常见陷阱。</p>
</div>
<a rel="nofollow" href="/xiazai/skill2334" title="MySQL" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>
-
COMMAND = 'Sleep'且TIME > 300:基本确认是应用拿了连接不放,事务空挂着 -
STATE = 'Locked'或'Updating'且TIME持续涨:SQL 可能卡在磁盘 I/O,或者正在等另一个锁释放 -
INFO字段显示最后执行语句,但它可能被截断(VARCHAR(1024)),也可能为空——尤其用了预处理且PDO::ATTR_EMULATE_PREPARES = true时
关联查询示例:
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';
MySQL 8.0+ 必须用 performance_schema.data_lock_waits 查等待链
INNODB_LOCK_WAITS 在 MySQL 8.0 已被移除,硬套老文档会查不到数据。正确路径是:
-
performance_schema.data_lock_waits提供明确的等待关系:REQUESTING_ENGINE_LOCK_ID对应等待方,BLOCKING_ENGINE_LOCK_ID对应持锁方 - 再通过
performance_schema.data_locks关联拿到具体表、索引、行信息 - 如果
data_lock_waits返回空,不代表没锁争用——可能是锁已释放、或等待时间太短没被捕获,此时要回头盯INNODB_TRX里的长RUNNING事务
简单等待链查询(MySQL 8.0+):
SELECT r.trx_id waiting_trx_id, r.trx_mysql_thread_id waiting_thread,
b.trx_id blocking_trx_id, b.trx_mysql_thread_id blocking_thread
FROM performance_schema.data_lock_waits w
JOIN information_schema.INNODB_TRX b ON b.trx_id = w.BLOCKING_TRX_ID
JOIN information_schema.INNODB_TRX r ON r.trx_id = w.REQUESTING_TRX_ID;
真正难的不是查到数据,而是区分“持锁者是正常业务逻辑卡住”还是“纯粹忘了提交”。很多问题藏在应用层:事务边界没对齐、异常分支漏 rollback、连接池配置不合理导致连接复用时事务残留。查完数据库,一定得回代码里看事务控制点。










