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,其中包含以下记录:
CREATE TABLE employees (
id INT PRIMARY KEY,
name VARCHAR(100)
);
INSERT INTO employees (id, name) VALUES (1, 'Alice'), (2, 'Bob'), (4, 'Charlie'), (5, 'David');
在一个事务中执行范围查询并加锁:FOR UPDATE
START TRANSACTION;
SELECT * FROM employees WHERE id BETWEEN 2 AND 4 FOR UPDATE;
此时,InnoDB 会锁定 (2, 4) 之间的间隙,防止其他事务在该范围内插入新记录。
在另一个事务中尝试插入新记录:
START TRANSACTION;
INSERT INTO employees (id, name) VALUES (3, 'Eve');
由于 (2, 4) 的间隙被锁定,第二个事务会被阻塞,直到第一个事务提交或回滚。
事务隔离级别与间隙锁
间隙锁在 MySQL 的 REPEATABLE READ(*) 和 SERIALIZABLE 隔离级别下生效。在 READ COMMITTED 和 READ UNCOMMITTED 隔离级别下,间隙锁通常不会被使用。
查询实例的隔离级别
SELECT @@global.tx_isolation;