查锁前须确认表引擎为InnoDB,因information_schema.innodb_locks仅显示InnoDB行级锁;MySQL 8.0+需改用performance_schema.data_locks;该表只反映当前持有锁,不显示等待锁或元数据锁。

查锁前先确认是不是 InnoDB 引擎
不是所有表都走 information_schema.innodb_locks —— 这张表只记录 InnoDB 的行级锁,MyISAM 表锁、LOCK TABLES 显式加的表锁、或者 Waiting for table metadata lock 这类元数据锁,它完全不显示。执行前务必确认目标表引擎:
SELECT engine FROM information_schema.tables WHERE table_schema = 'your_db' AND table_name = 'your_table';
如果不是 InnoDB,后面查 innodb_locks 就是空的,得换路子。
用 information_schema.innodb_locks 看实际持有的锁
这张表在 MySQL 5.7 及以前可用,但注意:从 MySQL 8.0.1 开始,innodb_locks 已被移除(改由 performance_schema.data_locks 替代)。如果你用的是 8.0+,直接查会报错 Table 'information_schema.innodb_locks' doesn't exist。
在支持的版本中,它返回的是「当前被事务持有着的锁」,不是等待中的锁。关键字段包括:
-
lock_trx_id:持有该锁的事务 ID,可关联innodb_trx查事务详情 -
lock_mode:常见值如S(共享锁)、X(排他锁)、REC_NOT_GAP(记录锁)、GAP(间隙锁) -
lock_page和lock_rec:能定位到具体页和记录偏移,但一般只需结合lock_index和lock_space看锁在哪张表哪个索引上
示例:只看某张表的锁
SELECT * FROM information_schema.innodb_locks
WHERE lock_trx_id IN (
SELECT trx_id FROM information_schema.innodb_trx
WHERE trx_mysql_thread_id IN (
SELECT id FROM information_schema.processlist
WHERE db = 'your_db'
)
) AND lock_space IN (
SELECT space FROM information_schema.innodb_sys_tables
WHERE name = 'your_db/your_table'
);用 show full processlist 补全阻塞链
processlist 不显示锁本身,但它告诉你谁卡住了、谁在等、谁可能正在干耗时操作。重点看三列:
-
State:值为Locked(MyISAM 表锁)、Waiting for table metadata lock(DDL 阻塞)、updating或sending data但Time很大,大概率是锁等待 -
Info:被截断的 SQL,配合Id去查完整语句(SELECT * FROM performance_schema.events_statements_current WHERE thread_id = ?) -
Time:持续秒数,超过innodb_lock_wait_timeout(默认 50 秒)还没结束,基本就是死锁或长事务占着不放
特别注意:processlist 里看到 Command = Sleep 但 State = NULL 且 Time 很大,说明事务没提交,锁还挂着——这是最常被忽略的“静默锁源”。
为什么 innodb_lock_waits 查不到等待关系
这张表只记录「当前正在发生的锁等待」,一旦等待超时或被杀掉,记录就消失。它不存历史,也不记录已释放的等待。所以你执行 SELECT * FROM information_schema.innodb_lock_waits 返回空,不代表没锁争用,可能只是等待刚结束、或者锁是元数据锁(MDL)这类非 InnoDB 锁。
更可靠的组合是:
- 先跑
SELECT * FROM information_schema.innodb_trx ORDER BY trx_started LIMIT 5,找运行时间长的事务 - 再用它的
trx_mysql_thread_id去processlist里查对应线程状态 - 如果看到多个线程
State是update或query且Time接近,再查它们是否在操作同一张表的同一索引范围
真正的锁冲突现场,往往藏在「长时间未提交事务 + 多个线程反复更新同一主键范围」这种组合里,而不是单靠一张表就能一眼看出。


















