sys.innodb_lock_waits是MySQL 5.7+最直白的锁等待链路入口,通过WAITING_TRX_ID和BLOCKING_TRX_ID扁平化展示阻塞关系,配合waiting_pid、blocking_pid、waiting_query等字段快速定位锁等待源头。

查 sys.innodb_lock_waits 直接看到“谁在等谁”
这个视图是 MySQL 5.7+(含 8.0)里最直白的锁等待链路入口,它把阻塞关系扁平化成两列:WAITING_TRX_ID 和 BLOCKING_TRX_ID。不需要拼表、不用猜,一行就告诉你哪个事务卡住了哪个事务。
执行 SELECT * FROM sys.innodb_lock_waits\G; 后重点关注:
-
waiting_pid和blocking_pid:对应PROCESSLIST.ID,可直接用于KILL -
waiting_query:被堵住的那条 SQL,但注意——它可能已被截断或为 NULL(比如事务只 BEGIN 未执行语句) -
blocking_query:**不一定存在**,因为持锁者可能早已执行完 SQL,只是事务没提交;此时得回溯它的TRX_STARTED时间 - 如果结果为空,不代表没锁等待——可能是锁已释放、或锁类型不触发该视图(如 MDL 锁)
用 sys.innodb_trx 找出“赖着不走”的长事务
sys.innodb_trx 是 information_schema.INNODB_TRX 的增强封装,字段更友好,自带运行时长计算(trx_started + trx_wait_started)。锁等待的根因八成藏在这里。
典型命令:SELECT trx_id, trx_mysql_thread_id, trx_state, trx_started, trx_wait_started, trx_query FROM sys.innodb_trx WHERE trx_state = 'LOCK WAIT' OR TIME_TO_SEC(TIMEDIFF(NOW(), trx_started)) > 60\G;
-
trx_state = 'LOCK WAIT':正在等锁,优先处理 -
TIME_TO_SEC(...) > 60:运行超 1 分钟的活跃事务,大概率是忘记 COMMIT 或卡在应用层 -
trx_query为空?别急着跳过——结合trx_mysql_thread_id去SHOW PROCESSLIST查Info字段,那里可能有最后执行的语句 - MySQL 8.0 中
trx_operation_state可辅助判断当前操作阶段(如 "fetching rows"),比老版本更准
为什么 sys.schema_table_lock_waits 有时比 innodb_lock_waits 更关键
当看到大量 Waiting for table metadata lock,说明不是 InnoDB 行锁问题,而是 DDL 或隐式锁表导致的 MDL 等待。这时候 sys.innodb_lock_waits 会完全沉默——它只管行级锁。
sys.schema_table_lock_waits 专治这类问题,它能直接关联到阻塞的 DDL 语句(如 ALTER TABLE)和被堵住的 SELECT/INSERT:
- 字段
blocking_statement显示持 MDL 锁的 SQL,常见于未提交事务后紧跟 DDL -
waiting_statement_type告诉你被堵的是查询、更新还是另一条 DDL - 注意:该视图依赖
performance_schema的table_lock_waits_summary_by_table,需确认已启用(setup_consumers中对应项为 YES) - DDL 卡住时,
SHOW PROCESSLIST里对应线程的State是Waiting for table metadata lock,但Info可能为空——必须靠这个视图定位源头
别跳过 sys.session:确认线程归属与业务上下文
拿到 blocking_pid 或 waiting_pid 后,不能直接 KILL。先查 SELECT * FROM sys.session WHERE thd_id = ?\G;,它比原生 PROCESSLIST 多两个关键字段:
-
conn_id:对应应用连接池里的连接 ID,可反向追踪到服务实例或 Pod -
current_statement:比PROCESSLIST.Info更可靠,尤其对预编译语句(PDO/MyBatis)也常能还原真实 SQL -
program_name(MySQL 8.0.28+):如果客户端设置了PROGRAM_NAME,这里会显示服务名(如 “order-service”),极大降低误杀风险 - 若
current_statement为空,再查sys.statements_history拉最近 10 条历史语句——很多锁问题源于上一条没提交的 UPDATE
锁信息转瞬即逝,sys 库里这些视图虽方便,但字段设计有取舍(比如省略了 LOCK_DATA 行值)。真要定位到具体哪几行被锁,还得切回 performance_schema.data_locks 配合 data_lock_waits ——那才是临界点上的显微镜。


















