间隙锁(Gap Lock)
简介
在 MySQL 中,间隙锁(Gap Lock)是 InnoDB 存储引擎的一种特殊类型的行级锁,用于防止幻读现象,确保事务的隔离级别达到可重复读(REPEATABLE READ)。
间隙锁主要在范围查询和唯一性检查时使用,它通过锁定索引记录之间的间隙,而不是锁定实际的索引记录或行。
它主要用于聚簇索引和辅助索引,防止其他事务在这些间隙中插入新记录,或者防止多个事务同时插入相同的值,从而避免幻读现象。
间隙锁只锁定范围,不锁定具体的索引记录对应的行数据,即锁定的区间是开区间(a,b)。
原理
在可重复读隔离级别下,InnoDB存储引擎使用多版本并发控制(MVCC)来维护数据的一致性。间隙锁是InnoDB中MVCC机制的一部分,它是通过锁定一个范围内的所有可能间隙,确保在同一事务的执行过程中,该范围内的数据不会发生变化。这样,在事务执行期间,其他事务无法在这些间隙中插入新记录,确保事务的一致性。
例如,如果一个表中有两条记录,其关键字值为10和20,间隙锁可以锁定从10到20之间的间隙,这意味着其他事务不能在这个范围内插入一个新的关键字值(如15)。但是,这些事务仍然可以查询、更新或删除这个范围内现有的记录。
如果是基于唯一索引或主键索引的唯一记录操作,即只操作一条记录,不会加间隙锁。
加锁流程
前提:操作的数据一定是某个范围内的,不能是单独的一条数据。
- 开始事务:启动一个事务。
- 执行范围查询:对特定的索引范围执行查询。
- 加间隙锁:InnoDB 在查询范围内加上间隙锁,锁定范围内的所有间隙,而不是具体的行。
- 执行操作:在持有间隙锁的情况下执行查询或修改操作。
- 释放锁:事务提交或回滚时,释放间隙锁。
间隙锁的使用场景
- 范围查询:当执行范围查询时,InnoDB 会在查询范围内加间隙锁,防止其他事务在该范围内插入新记录。例如,
SELECT * FROM example WHERE id BETWEEN 10 AND 20 FOR UPDATE
。 - 唯一性检查:在插入新记录时,InnoDB 可能会在唯一性检查过程中加间隙锁,以防止其他事务插入可能导致唯一性冲突的新记录。
- 防止幻读:在事务隔离级别为可重复读(REPEATABLE READ)时,InnoDB 使用间隙锁防止幻读现象,确保同一事务在两次查询之间看到的结果一致。
示例
假设有一个表 example
,包含以下数据:
CREATE TABLE example (
id INT PRIMARY KEY,
value VARCHAR(50)
);
INSERT INTO example (id, value) VALUES (5, 'A'), (10, 'B'), (15, 'C');
- 事务 A:
START TRANSACTION;
-- 对 id 在 10 到 20 之间的记录加间隙锁
SELECT * FROM example WHERE id BETWEEN 10 AND 20 FOR UPDATE;
- 事务 B:
START TRANSACTION;
-- 尝试插入 id = 12 的记录,会被阻塞
INSERT INTO example (id, value) VALUES (12, 'D');
在这个示例中:
- 事务 A 对
id
在 10 到 20 之间的范围加了间隙锁。 - 事务 B 尝试在该范围内插入新的记录
id = 12
,但由于间隙锁的存在,事务 B 的插入操作会被阻塞,直到事务 A 提交或回滚。
间隙锁的优点与缺点
优点:
- 防止幻读:间隙锁可以有效地防止幻读现象,即在一个事务内读取到另一个事务新增的记录。
- 提高并发性:允许多个事务在不同的数据范围内并行操作,提高了系统的并发能力。
缺点:
- 可能导致死锁:间隙锁可能增加死锁的概率,因为它们增加了事务之间锁定资源的复杂性。
- 性能影响:在某些情况下,间隙锁可能导致不必要的锁定,从而降低数据库的性能。
与其他锁的对比
锁类型 | 锁定粒度 | 作用范围 | 使用场景 | 并发性能 |
---|---|---|---|---|
表锁 | 表级别 | 整个表 | DDL 操作、大批量更新 | 低 |
行锁 | 行级别 | 特定行(索引记录) | 高并发读写 | 高 |
间隙锁 | 行级别(间隙) | 索引记录之间的间隙 | 防止幻读、范围查询、唯一性检查 | 中 |
插入意向锁 | 行级别 | 索引记录之间的间隙 | 高并发插入 | 高 |
总结
间隙锁是 MySQL InnoDB 存储引擎用于防止幻读现象的一种行级锁,通过锁定索引记录之间的间隙,确保在事务执行过程中数据的一致性。它主要用于范围查询和唯一性检查等场景,通过与行锁和意向锁配合,提供细粒度的并发控制和数据保护机制。在设计高并发系统时,理解和正确使用间隙锁有助于提升系统的性能和可靠性。