面试题答案
一键面试临键锁机制避免幻读问题原理
- 范围加锁:临键锁(Next-Key Lock)是行锁和间隙锁(Gap Lock)的组合。它会锁定某一行数据以及这一行数据前后的间隙。例如,表中有数据
id
为 1、3、5。当对id = 3
的行加临键锁时,不仅会锁定id = 3
这一行,还会锁定(1, 3)
和(3, 5)
这两个间隙。 - 阻止插入:在事务场景下,当一个事务持有临键锁时,其他事务无法在被锁定的间隙中插入新数据。这就防止了在当前事务执行范围内新数据的插入,从而避免了幻读。因为幻读本质就是在同一事务的两次相同查询中,第二次查询看到了第一次查询之后其他事务插入的新数据。
未使用临键锁时幻读可能出现的场景
假设有一张 students
表,结构如下:
CREATE TABLE students (
id INT PRIMARY KEY,
name VARCHAR(50)
);
表中已有数据:
INSERT INTO students (id, name) VALUES (1, 'Alice'), (3, 'Bob');
事务1:
START TRANSACTION;
-- 查询 id 大于 1 的学生
SELECT * FROM students WHERE id > 1;
-- 这里假设查询结果为 id = 3 的 Bob
-- 此时事务1未提交
事务2:
START TRANSACTION;
-- 插入一条新数据
INSERT INTO students (id, name) VALUES (2, 'Charlie');
COMMIT;
事务1:
-- 再次执行相同查询
SELECT * FROM students WHERE id > 1;
-- 此时查询结果除了 Bob,还出现了 Charlie,这就是幻读
COMMIT;
在上述场景中,如果使用临键锁,事务1在第一次查询 id > 1
时,会对 (1, +∞)
这个范围加临键锁,事务2在插入 id = 2
的数据时,由于 (1, 3)
间隙被锁定,插入操作会被阻塞,直到事务1提交或回滚,从而避免了幻读的发生。