最稳、最通用的方式是查 information_schema.innodb_trx 并过滤 trx_state = 'lock wait',可精准定位正在等待行锁的事务,结合 trx_wait_started 与 trx_query 判断阻塞时长和被堵sql,注意权限、mysql 8.0+需改用 performance_schema.data_lock_waits。

直接查 INNODB_TRX 筛出状态为 LOCK WAIT 的事务
最稳、最通用的方式是查 INFORMATION_SCHEMA.INNODB_TRX,过滤 trx_state = 'LOCK WAIT'。这个字段明确表示该事务已进入锁等待队列,正在等别人释放行锁。
- 执行:
SELECT trx_id, trx_mysql_thread_id, trx_query, trx_wait_started, trx_started FROM INFORMATION_SCHEMA.INNODB_TRX WHERE trx_state = 'LOCK WAIT'; -
trx_wait_started告诉你卡了多久,比trx_started更关键;若差值超几十秒,基本可断定是慢事务或未提交事务拖住的 -
trx_query是被堵住的 SQL,但可能为NULL(比如语句已执行完、只等锁);此时得靠trx_mysql_thread_id去sys.processlist或SHOW PROCESSLIST补全上下文 - 权限注意:普通用户默认看不到其他用户的
INNODB_TRX记录,查不到 ≠ 没有锁 —— 需确认是否拥有PROCESS权限
MySQL 8.0+ 必须用 performance_schema.data_lock_waits 关联查
在 MySQL 8.0 及以后版本,INFORMATION_SCHEMA.INNODB_LOCK_WAITS 已废弃且始终为空,不能依赖。必须转向 performance_schema,但需确保采集开关已打开。
- 先检查是否启用:
SELECT NAME, ENABLED FROM performance_schema.setup_instruments WHERE NAME IN ('wait/lock/innoDB/lock', 'wait/lock/innoDB/transaction');,若为NO,需执行UPDATE performance_schema.setup_instruments SET ENABLED = 'YES' WHERE NAME LIKE 'wait/lock/innoDB/%'; - 再查等待关系:
SELECT REQUESTING_ENGINE_TRANSACTION_ID AS waiting_trx_id, BLOCKING_ENGINE_TRANSACTION_ID AS blocking_trx_id FROM performance_schema.data_lock_waits; - 注意:
BLOCKING_ENGINE_TRANSACTION_ID是 InnoDB 内部事务 ID,必须和INNODB_TRX.trx_id匹配,不能误连trx_mysql_thread_id(类型不一致,查不到结果)
别信 SHOW OPEN TABLES WHERE In_use > 0
这条命令只反映表级锁或元数据锁(MDL),比如 ALTER TABLE 卡住时会显示,但它对 InnoDB 行锁完全不敏感。你看到 In_use = 0,不代表没行锁等待 —— 这是新手最常踩的坑。
- 行锁冲突不会让任何表的
In_use字段变非零 - 它查的是
table_open_cache中的引用计数,和事务锁机制无关 - 真要初筛有没有行锁等待,用更轻量的:
SHOW STATUS LIKE 'innodb_row_lock_current_waits';,返回值 > 0 就说明此刻正有事务卡着
为什么有时查不到等待事务,但业务明显卡住?
常见原因不是查询逻辑错,而是状态已过期或权限/配置限制。
- 锁等待是瞬时快照:
INNODB_TRX和data_lock_waits都只保留“当前正在发生”的状态;等你登录上去查,锁可能刚释放,结果为空 - 持锁者是内部线程:如 DDL 线程、后台 purge 线程,它们不在
sys.processlist中出现,也查不到对应trx_query -
performance_schema未启用或 consumers 关闭:即使开了 instruments,若setup_consumers中global_instrumentation或thread_instrumentation是NO,data_lock_waits仍为空 - 事务已提交但锁未及时清理:极少见,多见于崩溃恢复后状态异常,此时需结合
SHOW ENGINE INNODB STATUS\G中的LATEST DETECTED DEADLOCK或TRANSACTIONS区块人工交叉验证
trx_id 追到具体 SQL、判断它是否合理、以及确认它有没有被误杀风险。很多线上事故源于 KILL 错了长事务而非锁持有者 —— 所以拿到 trx_mysql_thread_id 后,务必先看 sys.processlist 的 STATE 和 TIME,再决定动不动手。











