data_locks的lock_type字段是mysql 8.0+判断锁类型的最直接依据,分为table(表级锁,含mdl等)和record(innodb行锁)两类,需结合innodb_trx、show engine innodb status等交叉验证。

看 performance_schema.data_locks 里的 LOCK_TYPE 字段
MySQL 8.0+ 中,data_locks 是判断锁类型最直接的依据。它把锁明确分为 TABLE 和 RECORD 两类:LOCK_TYPE = 'TABLE' 就是表级锁(含 MDL、显式 LOCK TABLES、MyISAM 表锁),LOCK_TYPE = 'RECORD' 才是 InnoDB 行锁(包括 record/gap/next-key)。注意:这里不显示“行锁”或“表锁”字样,只显示大写的类型名。
常见误判点:
-
LOCK_TYPE = 'TABLE'不一定代表 MyISAM 或手动加锁——MDL 锁也归在此类,但它是元数据锁,和传统表锁机制完全不同 -
LOCK_DATA字段对RECORD锁是十六进制编码的索引键值(如0x0102),对TABLE锁则为空或显示NULL - 如果查不到
RECORD锁但事务明显卡住,大概率是 MDL 锁(比如 ALTER 正在等慢查询释放读锁)
结合 INNODB_TRX 和状态字段交叉验证
单看 data_locks 可能漏掉关键上下文。必须关联 INNODB_TRX 查事务状态,重点关注 TRX_STATE 和 TRX_OPERATION_STATE:
-
TRX_STATE = 'LOCK WAIT'且TRX_OPERATION_STATE含updating或inserting→ 大概率是行锁等待 -
TRX_STATE = 'RUNNING'但长时间没推进,且其他事务在等它 → 它可能持有一个未提交的行锁,或更隐蔽地持有一个 MDL 读锁(比如执行了SELECT ... FROM huge_table但还没结束) - 状态显示
waiting for table metadata lock→ 直接锁定为 MDL 表级阻塞,和行锁无关
用 SHOW ENGINE INNODB STATUS\G 看锁等待链细节
这个命令输出里的 TRANSACTIONS 部分,比视图更贴近真实执行现场。重点扫三处:
- 找
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:下面的lock_mode X locks rec but not gap→ 明确是行锁 - 出现
lock_mode S or X on table→ 表锁(注意区分是 MDL 还是传统表锁,前者会标metadata lock) - 如果看到
Trx has been waiting 120 sec但没列具体锁模式 → 很可能是 MDL 等待,因为 MDL 不走 InnoDB 锁管理器,INNODB STATUS只提状态不列细节
为什么不能只依赖 SHOW PROCESSLIST
SHOW PROCESSLIST 的 State 列太笼统,容易误导:
-
Updating状态既可能是行锁等待,也可能是 MDL 写锁排队(比如 ALTER 卡住时,后续所有 SELECT 都显示Updating) -
Sending data看似正常,但如果背后是个长事务持有间隙锁,新 INSERT 仍会被堵死 - MyISAM 表的
Locked状态确实代表表写锁,但 InnoDB 下几乎不会出现这个词——一旦看到,基本说明混用了引擎或触发了隐式锁升级
真正难的不是识别锁类型,而是理解「为什么一个本该是行锁的操作退化成了表级效果」:比如没走索引的 UPDATE 会锁全表,或者 RR 隔离级别下间隙锁范围过大,让并发 INSERT 全部排队。这些场景下,data_locks 仍显示 RECORD,但实际影响等同于表锁。











