sys.innodb_lock_waits查不到数据,首要检查performance_schema是否启用、相关consumers是否开启、用户权限是否完备;三者缺一不可。

sys.innodb_lock_waits查不到数据,先检查这三件事
它返回空不是因为没锁,而是底层数据链断了。MySQL 8.0 中该视图是合成视图,依赖 performance_schema.data_locks、performance_schema.data_lock_waits 和 INFORMATION_SCHEMA.INNODB_TRX 三者 JOIN 生成。缺一不可:
-
SELECT VARIABLE_VALUE FROM performance_schema.global_variables WHERE VARIABLE_NAME = 'performance_schema'必须返回ON -
SELECT NAME, ENABLED FROM performance_schema.setup_consumers WHERE NAME IN ('events_statements_current', 'events_transactions_current', 'global_instrumentation')所有对应行的ENABLED值必须是YES - 执行用户必须有
SELECT ON performance_schema.*和PROCESS ON *.*权限;否则字段会静默为空甚至整行消失
blocking_pid为空或blocking_query为空,说明什么
这两个字段缺失,不代表没阻塞源,而是阻塞方可能处于“无活跃 SQL”的状态:
-
blocking_pid是information_schema.PROCESSLIST.Id,可直接用于KILL CONNECTION,但若为NULL,大概率是事务已执行完语句但未COMMIT(比如只跑了BEGIN就挂起) -
blocking_query为空时,别急着 kill;先查SELECT TRX_ID, TRX_MYSQL_THREAD_ID, TRX_QUERY, TRX_STARTED FROM information_schema.INNODB_TRX ORDER BY TRX_STARTED,找 TRX_STATE ='RUNNING'且TRX_STARTED很早的事务 - 这类长事务往往只持锁不等待,
sys.innodb_lock_waits不会显示它——因为它没被等,只是在“安静地堵路”
locked_table字段怎么解析才不误判热点表
locked_table 看似直观,但容易漏掉关键信息:
- 值形如
`db_name`.`table_name`,反引号是字面量,不能用字符串分割提取库名/表名(比如直接SUBSTRING_INDEX可能切错) - 它只反映被争抢的表,不体现锁粒度:
lock_type = 'RECORD'是行级锁,lock_type = 'TABLE'是表级锁(如 AUTO_INCREMENT),而 MDL 锁完全不会出现在这里 - 真要定位热点表,建议补查:
SELECT OBJECT_SCHEMA, OBJECT_NAME, LOCK_MODE, LOCK_DATA FROM performance_schema.data_locks WHERE ENGINE_TRANSACTION_ID = 'xxx';若LOCK_DATA为NULL或范围值(如7, 10),大概率是间隙锁,不是单行冲突
为什么看到sql_kill_blocking_connection却不敢执行
这个字段生成的语句看着省事,但直接运行风险很高:
-
sql_kill_blocking_connection对应的是KILL CONNECTION xxx,会干掉整个连接,如果该连接正处理重要业务(比如批处理中间态),可能引发数据不一致 - 若阻塞源是
MDL 锁(比如Waiting for table metadata lock),sys.innodb_lock_waits根本不捕获它;此时杀错连接毫无作用,得查sys.schema_table_lock_waits - 更稳妥的做法:先用
blocking_pid查SHOW PROCESSLIST确认State和Info,再判断是KILL QUERY还是KILL CONNECTION;对生产环境,优先KILL QUERY观察是否释放锁
真正难的不是查出谁在堵,而是区分“正在等锁”和“拿着锁不放但没人等它”——后者在 sys.innodb_lock_waits 里永远隐身,必须靠 INNODB_TRX + data_locks 联合确认。


















