mysql 8.0+ 中 sys.innodb_lock_waits 视图仍可用,是基于 performance_schema.data_lock_waits 和 data_locks 构建的兼容性封装;若返回空,需检查 global_instrumentation 是否启用,且该视图仅显示 waiting 状态锁等待,不包含已授予锁。

MySQL 8.0+ 中 sys.innodb_lock_waits 视图仍可用,但底层已不依赖废弃的 INNODB_LOCK_WAITS 表,而是自动基于 performance_schema.data_lock_waits 和 data_locks 构建——它是个兼容性封装,查它没问题,但得知道它背后实际走的是哪套机制。
为什么 sys.innodb_lock_waits 在 MySQL 8.0+ 还能返回结果
该视图是 sys 库提供的高层抽象,内部 SQL 已重写为 JOIN performance_schema.data_lock_waits 和 data_locks。所以即使你执行 SELECT * FROM sys.innodb_lock_waits,也不会报错或返回空——前提是 performance_schema 的相关采集器已启用。
- 若返回空集,先检查:
SELECT VARIABLE_VALUE FROM performance_schema.setup_consumers WHERE NAME = 'global_instrumentation';若为NO,需执行UPDATE performance_schema.setup_consumers SET ENABLED = 'YES' WHERE NAME = 'global_instrumentation' -
sys.innodb_lock_waits默认只展示LOCK_STATUS = 'WAITING'的锁等待关系,不包含已授予(GRANTED)的锁;如需看谁持有了锁,得直接查performance_schema.data_locks - 字段如
blocking_query可能为NULL:当阻塞方连接处于 idle 状态(比如事务未提交但没在跑 SQL),就无法捕获当前语句
怎么用 sys.innodb_lock_waits 快速定位“谁卡了谁”
核心目标是拿到 waiting_pid 和 blocking_pid,再结合 SHOW PROCESSLIST 查具体 SQL 和状态。
- 基础查询:
SELECT wait_age, object_schema, object_name, waiting_query, blocking_query, waiting_pid, blocking_pid, sql_kill_blocking_connection FROM sys.innodb_lock_waits - 加过滤条件避免干扰:
WHERE object_schema = 'your_db' AND object_name = 'your_table' -
sql_kill_blocking_connection字段给出的是可直接执行的KILL CONNECTION xxx命令,但注意:它杀的是整个连接,不是单条语句;若只想中断阻塞 SQL 而保留连接,优先用sql_kill_blocking_query(前提是阻塞方仍在执行中) - 如果
blocking_query是NULL,但blocking_trx_id存在,就去查:SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX WHERE TRX_ID = 'xxx',看TRX_STATE、TRX_STARTED和TRX_MYSQL_THREAD_ID(即对应blocking_pid)
sys.innodb_lock_waits 返回结果里关键字段怎么看
它把锁等待关系扁平化成一行,但字段含义容易误解:
-
lock_mode是请求锁的模式(比如X表示排他行锁),不是持有锁的模式;要看阻塞方用的什么锁,得看blocking_lock_mode -
lock_type是RECORD还是TABLE,决定了是行级冲突还是 DDL 类阻塞;若为TABLE且object_name是普通表,大概率是 ALTER TABLE 等操作被挂起 -
wait_age单位是秒,但精度受限于采样频率;它反映的是“当前等待持续时间”,不是累计值;同一行反复出现,说明阻塞未解除 -
waiting_query显示的是被阻塞的那条语句,但注意:它可能已被重试多次,真实业务逻辑可能早已超时退出,别只盯着这条 SQL 优化
真正麻烦的点不在查不到,而在于查到了却不敢杀、杀完又复发——比如长事务没提交、应用端没正确处理异常回滚、或者索引缺失导致锁范围过大。这些不会体现在 sys.innodb_lock_waits 的字段里,得结合 INNODB_TRX 的 TRX_ROWS_LOCKED 和执行计划一起看。











