查锁等待最快用innodb_lock_waits表,返回空表示无活跃锁等待;非空时通过requesting_trx_id和blocking_trx_id关联innodb_trx定位阻塞事务及sql,mysql 8.0+推荐用performance_schema.data_lock_waits。

查锁等待:直接看 INNODB_LOCK_WAITS 最快
有事务卡住不动?先别猜,INNODB_LOCK_WAITS 就是专为这事设计的——它只存“谁在等、等谁”的瞬时关系,一查就出结果。
- 执行
SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS;,如果返回空,说明此刻没有活跃锁等待(注意:不是“没锁”,而是“没卡住”) - 返回非空时,关键字段是
requesting_trx_id(等待方)和blocking_trx_id(挡路人),这两个 ID 必须立刻拿去查INNODB_TRX - ⚠️ 坑:
INNODB_LOCK_WAITS是快照,锁一释放就清空。等你反应过来再查,可能已经空了——得在卡顿发生的当下立刻执行
定位阻塞源头:用 trx_mysql_thread_id 找到真凶 SQL
光知道哪个事务 ID 在挡路没用,得看到它正在跑什么语句、有没有忘提交、是不是睡着了。
- 拿
blocking_trx_id去查INNODB_TRX:SELECT trx_id, trx_state, trx_started, trx_mysql_thread_id, trx_query FROM INFORMATION_SCHEMA.INNODB_TRX WHERE trx_id = 'xxx'; -
trx_state是重点:如果是RUNNING且trx_started是几分钟前,大概率是长事务;如果是LOCK WAIT,说明它自己也被卡住了,链式阻塞开始了 -
trx_mysql_thread_id可直接用于KILL,但注意:它和SHOW PROCESSLIST里的ID通常一致,但不绝对——优先信这个字段 - ⚠️ 坑:普通用户默认查不到其他用户的
INNODB_TRX,会误判“没锁”。需提前授PROCESS权限
MySQL 8.0+ 推荐换用 performance_schema.data_lock_waits
旧的 INNODB_LOCKS 表在 8.0 已移除,data_lock_waits 不仅字段更清晰,还能关联具体表名、行锁对象,排查粒度更细。
- 查等待关系:
SELECT r.OBJECT_NAME, r.LOCK_MODE AS requested_mode, b.LOCK_MODE AS blocking_mode, r.OWNER_THREAD_ID, b.OWNER_THREAD_ID FROM performance_schema.data_lock_waits w JOIN performance_schema.data_locks r ON w.REQUESTING_ENGINE_LOCK_ID = r.ENGINE_LOCK_ID JOIN performance_schema.data_locks b ON w.BLOCKING_ENGINE_LOCK_ID = b.ENGINE_LOCK_ID; - 支持按库过滤:
WHERE r.OBJECT_SCHEMA = 'your_db',避免被无关库干扰 - 性能影响小,但需确认
performance_schema已启用,且data_locks和data_lock_waits的 consumers 已打开(默认通常开启)
辅助验证:用 SHOW ENGINE INNODB STATUS\G 看上下文
当锁等待链条复杂、或者想确认是否刚发生过死锁,这个命令不可跳过。它不提供结构化结果,但能还原现场。
- 重点关注
TRANSACTIONS部分:每条事务下面会写明waiting for this lock和holds the following locks,直接对应到索引、页、记录 -
LATEST DETECTED DEADLOCK区域会完整列出两个冲突事务的 SQL、持有的锁、等待的锁,是分析死锁的唯一权威来源 - ⚠️ 坑:
SHOW ENGINE INNODB STATUS输出是循环缓冲区,只保留最近一次死锁和部分事务快照。如果没及时看,就丢了——建议卡顿时顺手执行,别等“稍后整理”
锁问题最麻烦的从来不是查不到,而是查到了却不敢杀、不敢改、不敢动。真正卡住系统的,往往是一个忘了 COMMIT 的连接,或一条没走索引的 UPDATE。这些细节藏在 trx_query 和 trx_started 里,不在视图结构中,而在你多看一眼的那两行输出里。











