MySQL 的锁机制是其并发控制的核心,直接影响数据库的性能、一致性与可用性。本文将从底层原理、锁的分类、实现机制、锁的粒度、锁的兼容性、死锁处理、InnoDB 的行锁实现、MVCC 与锁的关系等多个维度,进行硬核、深度解析,适用于希望深入理解 MySQL 并发控制机制的开发者与 DBA。
一、MySQL 锁机制概览
MySQL 的锁机制主要由存储引擎层实现,不同引擎的锁策略不同:
- MyISAM:仅支持表级锁(Table-level Locks)
- InnoDB:支持行级锁(Row-level Locks)、表级锁、意向锁、间隙锁、临键锁等,是目前最复杂的锁系统
我们以 InnoDB 为主进行深度剖析。
二、InnoDB 锁的类型与分类
1. 按粒度划分
锁类型 | 粒度 | 说明 |
---|---|---|
表级锁 | Table Lock | 锁整张表,开销小,但并发低 |
行级锁 | Row Lock | 锁具体行,高并发,开销大 |
页级锁 | Page Lock | 锁一页(如 16KB),介于表与行之间(BDB 支持,InnoDB 不用) |
InnoDB 实现的是逻辑行级锁,物理上通过索引项加锁实现。
2. 按模式划分(共享锁 vs 排他锁)
锁类型 | 别名 | SQL 语法 | 兼容性 |
---|---|---|---|
共享锁(S Lock) | 读锁 | SELECT ... LOCK IN SHARE MODE | 多个 S 锁可共存 |
排他锁(X Lock) | 写锁 | SELECT ... FOR UPDATE 或 UPDATE/DELETE | 仅一个 X 锁,不与 S/X 兼容 |
兼容性矩阵:
请求 \ 持有 | S(共享) | X(排他) |
---|---|---|
S | ✅ 兼容 | ❌ 不兼容 |
X | ❌ 不兼容 | ❌ 不兼容 |
3. 意向锁(Intention Locks)
目的:提高表级锁与行级锁的兼容性检测效率。
- IX(Intention Exclusive):事务打算在某些行上加 X 锁
- IS(Intention Shared):事务打算在某些行上加 S 锁
意向锁的规则:
- 意向锁是表级锁,但表示的是对行加锁的“意图”
- 意向锁之间完全兼容(IS 与 IX 可共存)
- 真正的冲突发生在行锁之间
示例:
-- 事务 T1
BEGIN;
SELECT * FROM t WHERE id = 1 FOR UPDATE; -- 加 IX + 行 X 锁
此时其他事务若想对整表加 X 锁(如 LOCK TABLES t WRITE
),会检测到 IX,拒绝加锁。
4. 行锁的实现方式:记录锁(Record Lock)
- 锁住索引上的单个记录
- 如果表没有主键,InnoDB 会隐式创建一个 6 字节的
ROWID
作为聚簇索引,行锁基于此
-- 假设 id 是主键
SELECT * FROM t