查锁等待关系应优先执行select * from information_schema.innodb_lock_waits;若返回非空,需立即记录requesting_trx_id和blocking_trx_id,并通过innodb_trx定位阻塞事务状态;mysql 8.0+须改用performance_schema.data_lock_waits,同时不可忽略mdl锁导致的waiting for table metadata lock现象。

查锁等待关系,直接看 INNODB_LOCK_WAITS 表
只要事务卡住没响应,第一反应不是猜、不是翻日志,而是立刻执行:SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS;
返回空?说明此刻没有活跃锁等待(注意:不等于“没锁”,只是没人卡着);返回非空?那两个关键字段必须马上记下来:requesting_trx_id(等锁的事务)、blocking_trx_id(占着锁不放的事务)。
这个表是快照机制,锁一释放就清空——等你缓过神再查,大概率已经为空了。
定位阻塞源头,用 blocking_trx_id 查 INNODB_TRX
拿到 blocking_trx_id 后,立刻去查真实执行状态: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,但要注意:普通用户默认无权查其他用户的 INNODB_TRX,需提前授予 PROCESS 权限,否则会误判为“没阻塞源”
MySQL 8.0+ 用户该切到 performance_schema.data_lock_waits
INNODB_LOCKS 表在 MySQL 8.0 已被移除,继续用会报错。新路径是: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';
优势很明显:
- 字段名更直白(比如 OBJECT_NAME 直接显示表名)
- 支持按库过滤,避免跨库干扰
- 能关联到具体行锁对象,粒度更细
前提是 performance_schema 已启用,且 data_locks 和 data_lock_waits 的 consumers 处于开启状态(默认通常开启,但生产环境建议确认)
别漏掉 MDL 锁这种“隐形阻塞”
如果 INNODB_LOCK_WAITS 为空,但 SHOW PROCESSLIST 里有语句卡在 Waiting for table metadata lock,那就是 MDL 锁在作怪——它不走 InnoDB 锁体系,查不到 INNODB_* 表里。
此时要转向 performance_schema.metadata_locks 和 sys.schema_table_lock_waits(如果 sys 库已安装):SELECT * FROM performance_schema.metadata_locks WHERE LOCK_STATUS = 'PENDING';
再关联 performance_schema.threads 找出持有锁的线程和 SQL。这类锁常由未完成的 DDL(如 ALTER TABLE)或长事务中的 SELECT 引发,排查路径和行锁完全不同。











