看锁的原始现场
performance_schema.data_locks 与 data_lock_waits 是 InnoDB 锁的结构化现场:前者每行一把锁,后者每行一条等待关系,精确到索引与记录,比 SHOW ENGINE INNODB STATUS 的文本快照更适合排查。定位顺序是先看等待关系找阻塞链,再回到锁清单确认锁住的具体记录与索引。
基本信息
| 适用 | MySQL 8.0;5.7 对应 information_schema.innodb_locks,字段不同 |
|---|---|
| 数据来源 | performance_schema.data_locks / data_lock_waits |
| 权限要求 | 需要 PROCESS 权限才能看到全部会话信息 |
| 开销 | 查询本身有成本,属排障工具而非长期监控手段 |
锁现场快查
锁现场快查
SELECT ENGINE_TRANSACTION_ID, OBJECT_NAME, INDEX_NAME, LOCK_TYPE, LOCK_MODE, LOCK_STATUS, LOCK_DATA FROM performance_schema.data_locks ORDER BY OBJECT_NAME; # 当前所有锁
SELECT * FROM performance_schema.data_lock_waits; # 谁在等谁
SELECT trx_id, trx_state, trx_started, trx_mysql_thread_id FROM information_schema.innodb_trx; # 关联出事务与线程
SELECT ID, USER, TIME, INFO FROM information_schema.processlist WHERE ID = <阻塞线程号>; # 定位具体 SQL字段读法
| 字段 | 含义 | 怎么用 |
|---|---|---|
| LOCK_TYPE | TABLE 或 RECORD | TABLE 多为意向锁,RECORD 才是行级细节 |
| LOCK_MODE | X、S、IS、IX 及 REC_NOT_GAP、GAP 等组合 | 判断是记录锁、间隙锁还是意向锁 |
| LOCK_STATUS | GRANTED 或 WAITING | WAITING 才是被挡住的,GRANTED 是持有方 |
| LOCK_DATA | 记录锁时显示主键值,表锁显示 NULL | 配合业务查询定位到底卡在哪条数据上 |
| INDEX_NAME | 定位记录所用索引 | PRIMARY 或二级索引名,缺失说明走了全表 |
| ENGINE_TRANSACTION_ID | 事务号 | 与 innodb_trx 关联即可找出对应 SQL |
典型使用场景
- 接口大面积超时,先确认是锁等待而不是慢 SQL
- 定位阻塞源:从等待链追到持有方事务,再决定 kill 还是等待
- 评估 UPDATE 的影响范围:确认是否意外锁住范围而不是单行
- 验证索引改造效果:改造后间隙锁是否减少、锁范围是否收窄
- 复盘死锁:结合最后一次死锁快照与当前锁清单确认加锁顺序
等待链的读法:data_lock_waits 一行里 REQUESTING 是等待方、BLOCKING 是持有方,两者的引擎事务号都能回到 innodb_trx 再关联 processlist 拿到 SQL。
高频轮询这两张表会引入额外开销并可能加剧争用,排障时短时打开即可;长期监控应改用锁等待相关的状态指标。
相关视图怎么配合
- SHOW ENGINE INNODB STATUS 给的是文本快照,适合快速看趋势,字段细节不如 data_locks
- sys.innodb_lock_waits 是视图封装,日常定位阻塞链更省事
- performance_schema.metadata_locks 管的是表结构与元数据锁,与行锁是两套体系
- information_schema.innodb_trx 用来把事务号还原成具体的 SQL 与线程