首页/数据/数据库速查/performance_schema.data_locks 解读
性能与调优57 条

performance_schema.data_locks 解读

P_S 的 data_locks / data_lock_waits 是锁的原始现场:每行的 LOCK_TYPE/LOCK_MODE/LOCK_DATA 精确到索引与记录,比 SHOW 输出更细。

数据库速查数据更新于 2026-10-13

看锁的原始现场

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_TYPETABLE 或 RECORDTABLE 多为意向锁,RECORD 才是行级细节
LOCK_MODEX、S、IS、IX 及 REC_NOT_GAP、GAP 等组合判断是记录锁、间隙锁还是意向锁
LOCK_STATUSGRANTED 或 WAITINGWAITING 才是被挡住的,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 与线程

易错点

  • 只看到 TABLE 行就以为没有行锁:行级细节在 RECORD 行里,需要按 LOCK_TYPE 区分
  • 把 GRANTED 当成问题锁:真正需要处理的是 WAITING 与它对应的 BLOCKING 事务
  • 只 kill 等待方不处理持有方:长事务还在,下一个请求照样被挡住
  • 在 5.7 上照抄 8.0 的表名与字段:旧版本用 information_schema.innodb_locks,字段与语义都不同

数据来源与参考

  • MySQL 8.0 Reference Manual: performance_schema.data_locks

相关工具

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌