MySQL 的锁层级与类型
在 MySQL 中,锁的层级和实现与存储引擎密切相关。
1. 表级锁(Table-Level Locks)
(1)存储引擎层的表级锁
- 实现层级:存储引擎层(如 MyISAM、InnoDB)。
- 特点:
- 粒度粗:锁定整张表,并发性能较低。
- 适用场景:适合读多写少或全表操作(如 MyISAM 引擎的读/写锁)。
- 示例:
- MyISAM 的表锁:
MyISAM 默认使用表级锁,分为 共享读锁(S锁) 和 排他写锁(X锁)。
例如,执行SELECT
时加读锁,INSERT/UPDATE
时加写锁。 - InnoDB 的表锁:
InnoDB 在特定场景(如未命中索引的全表扫描)可能升级行锁为表级锁。
- MyISAM 的表锁:
(2)Server 层的表级锁(元数据锁,MDL)
- 实现层级:Server 层。
- 特点:
- 隐式管理:由 MySQL Server 自动加锁,用于保护表结构(DDL 操作)。
- 锁冲突:DML(如
SELECT/INSERT
)与 DDL(如ALTER TABLE
)会触发 MDL 锁冲突。
- 示例:
执行ALTER TABLE
时,MySQL Server 会加 MDL 写锁,阻塞其他会话的 DML 操作。
2. 行级锁(Row-Level Locks)
实现层级:存储引擎层(仅 InnoDB 支持)。
- 特点:
- 粒度细:仅锁定需要操作的行,并发性能高。
- 支持事务:通过 MVCC(多版本并发控制)实现非锁定读。
- 锁类型:
- 共享锁(S 锁):允许其他事务读,但禁止写。
- 排他锁(X 锁):禁止其他事务读或写。
- 间隙锁(Gap Lock):锁定索引记录间的间隙,防止幻读。
- 示例:
执行SELECT ... FOR UPDATE
时,InnoDB 会对符合条件的行加排他锁。
3. 对比表级锁与行级锁
特性 | 表级锁 | 行级锁 |
---|---|---|
粒度 | 锁定整张表 | 锁定单行或多行 |
并发性能 | 低(锁冲突概率高) | 高(锁冲突概率低) |
存储引擎 | MyISAM(默认)、InnoDB(特殊情况) | InnoDB(默认支持) |
适用场景 | 全表操作、读多写少 | 高并发写、事务隔离(如 RC/RR 级别) |
实现层级 | 存储引擎层(MyISAM/InnoDB) + Server 层(MDL) | 存储引擎层(仅 InnoDB) |
4. 关键注意事项
-
InnoDB 的锁升级:
- 当行锁数量过多或未命中索引时,InnoDB 可能将行锁升级为表级锁。
- 示例:
UPDATE table SET col=1 WHERE unindexed_col=10
(全表扫描触发表锁)。
-
死锁风险:
- 行级锁可能引发死锁(如事务 A 锁行 1,事务 B 锁行 2,互相等待)。
- InnoDB 会自动检测死锁并回滚代价较小的事务。
-
显式锁与隐式锁:
- 显式锁:通过
LOCK TABLES
或SELECT ... FOR UPDATE
手动加锁。 - 隐式锁:由存储引擎自动管理(如 DML 语句触发的行锁)。
- 显式锁:通过
5. 总结
- 表级锁:
- 存储引擎层:MyISAM 默认使用,InnoDB 在特殊场景下触发。
- Server 层:元数据锁(MDL)保护表结构。
- 行级锁:
- 仅 InnoDB 支持,通过 MVCC 和锁机制实现高并发事务。
- 默认细粒度锁,避免全表锁定。