MySQL 的间隙锁(Gap Lock)
间隙锁(Gap Lock)是 InnoDB 存储引擎中的一种锁机制,用于防止幻读现象。幻读是指在一个事务中,两次读取同一个范围的数据时,第二次读取出现了第一次没有出现的数据行。间隙锁通过锁定一个范围内的"间隙"来防止其他事务在该范围内插入新记录,从而避免幻读。
间隙锁的特性
锁定范围 :间隙锁锁定的是记录之间的间隙,而不是具体的记录。例如,如果表中有记录 1, 2, 4, 5
,那么间隙锁可能锁定 (2, 4)
之间的间隙。
防止插入 :间隙锁可以防止其他事务在锁定的间隙范围内插入新记录。例如,如果间隙 (2, 4)
被锁定,则不能在 2
和 4
之间插入新的记录。
共享锁:间隙锁是共享锁,多个事务可以同时持有同一个间隙锁,但这些事务都不能在该间隙范围内插入新记录。
间隙锁的使用场景
间隙锁通常在以下场景中使用:
- 范围查询 :在执行范围查询时,例如
SELECT * FROM table WHERE column BETWEEN value1 AND value2 FOR UPDATE
,InnoDB 会使用间隙锁来锁定查询范围内的间隙。 - 范围删除 :在执行范围删除时,例如
DELETE FROM table WHERE column BETWEEN value1 AND value2
,InnoDB 也会使用间隙锁来锁定删除范围内的间隙。
示例
假设我们有一个表 employees
,其中包含以下记录:
sql
CREATE TABLE employees (
id INT PRIMARY KEY,
name VARCHAR(100)
);
INSERT INTO employees (id, name) VALUES (1, 'Alice'), (2, 'Bob'), (4, 'Charlie'), (5, 'David');
在一个事务中执行范围查询并加锁:
sql
START TRANSACTION;
SELECT * FROM employees WHERE id BETWEEN 2 AND 4 FOR UPDATE;
此时,InnoDB 会锁定 (2, 4)
之间的间隙,防止其他事务在该范围内插入新记录。
在另一个事务中尝试插入新记录:
sql
START TRANSACTION;
INSERT INTO employees (id, name) VALUES (3, 'Eve');
由于 (2, 4)
的间隙被锁定,第二个事务会被阻塞,直到第一个事务提交或回滚。
事务隔离级别与间隙锁
间隙锁在 MySQL 的 REPEATABLE READ 和 SERIALIZABLE 隔离级别下生效。在 READ COMMITTED 和 READ UNCOMMITTED 隔离级别下,间隙锁通常不会被使用。
总结
间隙锁是 InnoDB 用于防止幻读的一种锁机制,通过锁定记录之间的间隙,防止其他事务在该范围内插入新记录。间隙锁在范围查询和范围删除操作中尤为重要,确保了事务的一致性和隔离性。在实际应用中,理解和正确使用间隙锁可以帮助开发者构建更加健壮和可靠的数据库应用。