schema_table_lock_waits仅监控mdl表级元数据锁阻塞,专用于定位ddl(如alter table)被长事务中select等持有的s级mdl锁阻塞的问题;它不采集innodb行锁、间隙锁或临键锁,因底层依赖performance_schema.metadata_locks而非data_locks,故无法反映lock wait状态的行级锁冲突。

schema_table_lock_waits 只反映表级元数据锁(MDL)阻塞,查不到行锁、间隙锁或临键锁;它不是“锁监控总览”,而是专门定位 ALTER TABLE、DROP TABLE 等 DDL 被阻塞的场景。
为什么 schema_table_lock_waits 查不到行锁等待
这个视图底层依赖 performance_schema.metadata_locks(MySQL 5.7+)或 sys 封装逻辑,只采集 MDL 类型锁:比如一个 SELECT 持有 SHARED_READ MDL,会阻塞后续 ALTER TABLE 请求的 EXCLUSIVE MDL —— 这类关系它能捕获。但 InnoDB 行锁由 performance_schema.data_locks 管理,完全不在它的数据源范围内。
常见错误现象:
- 业务 UPDATE 卡住,
SHOW PROCESSLIST显示update ... LOCK WAIT,但SELECT * FROM sys.schema_table_lock_waits返回空 - 误以为“没锁问题”,实际是行锁冲突,该视图根本不会上报
怎么正确用 schema_table_lock_waits 定位 DDL 阻塞
它适合快速回答:“谁在拦着我改表?”——重点看 blocking 和 waiting 的线程 ID、SQL、锁类型和持续时间。
- 必须确保 MySQL ≥ 8.0(5.7 不含此视图),且
performance_schema已启用(SELECT @@performance_schema返回ON) - 执行
SELECT * FROM sys.schema_table_lock_waits\G,关注字段:blocking_pid(持有锁的连接 ID)、waiting_query(被卡住的 DDL)、blocking_lock_type(如SHARED_READ表示一个长事务里的普通 SELECT 正锁着表) -
sql_kill_blocking_query字段直接给出可执行的 KILL 命令,但注意:KILL QUERY 只中断语句,不结束事务;若事务未提交,MDL 仍被持有,得用KILL <code>blocking_pid彻底干掉连接
data_lock_waits 才是查行锁等待的正解(MySQL 8.0+)
当 schema_table_lock_waits 查不到东西,但事务状态确实是 LOCK WAIT,就得切到 performance_schema.data_lock_waits。
- 它需要先确认采集器开启:
UPDATE performance_schema.setup_consumers SET ENABLED = 'YES' WHERE NAME = 'global_instrumentation'; - 核心查询要 JOIN
data_locks两次(一次是等待方,一次是持有方),用OWNER_THREAD_ID关联information_schema.PROCESSLIST才能拿到真实 SQL -
data_lock_waits是瞬时快照:锁一释放,记录就消失。不能靠它看历史趋势,得配合innodb_row_lock_current_waits(状态变量)判断是否高频发生
真正容易被忽略的点是:同一个事务可能既持有 MDL(比如刚执行完一个 SELECT),又持有行锁(比如接着 UPDATE 了某行),但 schema_table_lock_waits 和 data_lock_waits 各管一摊,必须分开查、交叉印证——没有单个视图能覆盖所有锁类型。











