sys.innodb_lock_waits表不存在是因为sys schema未初始化;先用show schemas like 'sys'确认是否存在,若不存在则需通过mysql自带脚本重建。

查不到 sys.innodb_lock_waits?先确认 sys 库是否启用
这个表默认存在,但前提是 sys schema 已被初始化(MySQL 5.7+ 自带,但某些精简版或旧部署可能没装)。如果执行 SELECT * FROM sys.innodb_lock_waits; 报错 Table 'sys.innodb_lock_waits' doesn't exist,不是语法问题,是 schema 缺失。
- 运行
SHOW SCHEMAS LIKE 'sys';确认存在 - 若不存在,用 MySQL 自带脚本重建:
mysql -u root -p (路径依安装方式而异,常见于 <code>/usr/share/mysql/或/usr/local/mysql/share/) -
sys库依赖performance_schema,确保它已开启:SELECT VARIABLE_VALUE FROM performance_schema.global_variables WHERE VARIABLE_NAME = 'performance_schema';返回ON
sys.innodb_lock_waits 返回空?检查事务活跃状态
该视图只展示「当前正在发生的锁等待」,不是历史记录,也不是所有阻塞都实时可见。空结果不等于没锁,可能是:
- 等待刚发生还没被采样到(
sys视图基于performance_schema的定时采集,有毫秒级延迟) - 持有锁的事务已提交或回滚,等待链已断开
- 锁类型不被覆盖(比如 MDL 锁、表级锁不在此视图中)
- 用户权限不足:需要
SELECT权限在sys和performance_schema库
更可靠的兜底方式是直接查底层:SELECT * FROM performance_schema.data_lock_waits;(MySQL 8.0.1+)或结合 information_schema.INNODB_TRX + INNODB_LOCKS(5.7 中已废弃,但部分版本仍可用)
字段怎么看?重点关注 blocking_trx_id 和 waiting_trx_id
这个视图本质是把锁等待关系“翻译”成可读字段,核心是定位谁卡了谁。别被一堆列绕晕,盯住三组关键 ID:
-
waiting_trx_id:正在等锁的事务 ID(对应INNODB_TRX.TRX_ID) -
blocking_trx_id:持锁不放的事务 ID -
waiting_pid和blocking_pid:对应进程 ID,可直接杀掉:KILL <code>blocking_pid;
示例输出片段:
waiting_trx_id: 12345 blocking_trx_id: 67890 waiting_pid: 1024 blocking_pid: 1023
说明 PID 1024 卡在 PID 1023 手里 —— 此时去查 SELECT * FROM information_schema.INNODB_TRX WHERE TRX_ID = '67890'; 就能看到它在跑哪条 SQL、持续多久、是否在 sleep
为什么查到 blocking 事务却找不到对应 SQL?常见原因
经常看到 blocking_trx_id 存在,但查 INNODB_TRX 时该事务没了,或者 TRX_QUERY 是 NULL。这不是数据错乱,而是:
- 事务处于非活动状态(比如在等待用户输入、网络慢、应用层没提交)——
TRX_STATE是LOCK WAIT或ACTIVE才有 SQL;TRX_STATE = 'RUNNING'且TRX_QUERY IS NULL很可能在做内部操作(如大事务回滚、DDL) - SQL 已执行完,事务未提交,此时只有事务上下文,无当前语句(
TRX_QUERY为空) - 使用了 prepared statement,原始 SQL 不会出现在
TRX_QUERY,得结合performance_schema.events_statements_current查
真正要定位根因,得连查三张表:INNODB_TRX(看事务状态)、INNODB_LOCKS(看锁对象)、INNODB_LOCK_WAITS(看等待关系),缺一不可
锁等待不是孤立事件,背后往往是长事务、没索引的 UPDATE/DELETE、或应用层忘记 commit。查到 blocking_pid 后,别急着 kill,先看它在干什么——有时候 kill 反而触发更长的回滚。











