2. 数据库锁基础:锁的粒度、类型与兼容性矩阵

锁是数据库并发控制的核心机制,用于保证事务隔离性与数据一致性。理解锁的粒度、类型及其兼容关系,是排查锁等待与死锁问题的前提。本节从三个维度系统梳理数据库锁的基础知识。

2.1 锁的粒度

锁粒度指锁定资源的大小范围。粒度越细,并发度越高,但锁管理开销越大;粒度越粗,并发度越低,但开销小。主流数据库支持以下三种粒度:

粒度 锁定范围 并发度 开销 典型场景
行锁 单行记录 高 高 OLTP 高并发更新、InnoDB 默认
页锁 数据页(通常 4KB~16KB) 中 中 SQL Server、MySQL BDB 引擎
表锁 整张表 低 低 DDL 操作、MyISAM 引擎、批量维护
实战提示:MySQL InnoDB 默认使用行锁,但若查询未走索引,行锁会升级为表锁,导致并发骤降。排查锁等待时,优先检查 SQL 是否命中索引。
锁粒度层级结构图 锁粒度层级结构 表锁(Table Lock) 页锁(Page Lock) 行锁(Row Lock) 粒度对比 • 表锁:并发最低,开销最小 • 页锁:并发中等,开销中等 • 行锁:并发最高,开销最大 • 粒度越细,锁冲突概率越低 • 但锁管理内存消耗越大

2.2 锁的类型

根据读写行为,锁分为共享锁与排他锁;为提升多粒度加锁效率,数据库引入意向锁。三种基本类型定义如下:

  • 共享锁(S Lock,Shared Lock):允许持有事务读取数据,其他事务可继续加 S 锁,但不能加 X 锁。对应 SELECT ... LOCK IN SHARE MODE。
  • 排他锁(X Lock,Exclusive Lock):允许持有事务读写数据,其他事务不能加任何锁。对应 SELECT ... FOR UPDATE 或 UPDATE/DELETE。
  • 意向锁(Intention Lock):表级锁,用于快速判断表内是否已有行级锁,避免逐行检查。分为意向共享锁(IS)和意向排他锁(IX)。
关键理解:意向锁不阻塞任何行级锁请求,只用于表级锁与行级锁之间的协议通信。例如,事务在行上加 X 锁前,必须先在该表上加 IX 锁。

2.3 锁的兼容性矩阵

锁兼容性决定两个锁能否同时加在同一资源上。下表列出 S、X、IS、IX 四种锁在表级或行级上的兼容关系:

已持有锁 →
请求锁 ↓
共享锁(S) 排他锁(X) 意向共享锁(IS) 意向排他锁(IX)
共享锁(S) ✅ 兼容 ❌ 冲突 ✅ 兼容 ❌ 冲突
排他锁(X) ❌ 冲突 ❌ 冲突 ❌ 冲突 ❌ 冲突
意向共享锁(IS) ✅ 兼容 ❌ 冲突 ✅ 兼容 ✅ 兼容
意向排他锁(IX) ❌ 冲突 ❌ 冲突 ✅ 兼容 ✅ 兼容
排查要点:锁等待通常发生在 X 锁与 S/X 锁冲突时。若监控发现大量 IX 锁等待 IX 锁,往往不是锁冲突,而是资源排队(如 IO 慢、大事务未提交)。注意区分“锁冲突”与“锁等待”。
锁兼容性矩阵可视化 锁兼容性矩阵(S / X / IS / IX) 请求锁 S X IS IX S X IS IX 已持有锁 → 兼容 冲突 兼容 冲突 冲突 冲突 冲突 冲突 兼容 冲突 兼容 兼容 冲突 冲突 兼容 兼容 兼容 冲突

2.4 锁等待与死锁的初步判断

基于锁兼容性矩阵,可以快速定位锁等待原因:

  • 锁等待:事务 B 请求的锁与事务 A 已持有的锁不兼容,B 进入等待队列。常见于 SELECT ... FOR UPDATE 与 UPDATE 冲突。
  • 死锁:事务 A 等待 B 释放锁,事务 B 同时等待 A 释放锁,形成循环等待。数据库会自动检测并回滚代价较小的事务。
排查口诀:“S 不挡 S,X 挡所有;IX 只挡 S/X,不挡 IS/IX。” 记住这个口诀,90% 的锁等待场景可以快速归因。