===============
1 准备数据
1.1 建表
DROP TABLE IF EXISTS employee; CREATE TABLE IF NOT EXISTS employee ( id INT PRIMARY KEY, name VARCHAR(40), money INT )ENGINE INNODB;
1.2 插入数据
INSERT INTO employee(id, name, money) VALUES(1, 'Alice', 10000); INSERT INTO employee(id, name, money) VALUES(3, 'Bob', 10000);
提示:这里插入了 id=1 & id=3 的两条记录,偏偏没有插入 id=2 的记录,这是为什么呢?后面会用到。
2 测试
2.1 准备
还是老规矩,两个会话(终端),左边是白色背景的,右边是黑色背景的,并且均设置 autocommit = 0
2.2 测试
2.2.1 在左侧会话中执行更新
Sql 语句:
UPDATE employee SET money = money + 10000 WHERE id >= 1 AND id <= 3;
结果:
2.2.2 在右侧会话中执行插入
Sql 语句:
INSERT INTO employee(id, name) VALUES(2, 'David');
结果:
被阻塞!间隙锁导致的。
2.2.3 左侧执行提交
提示:注意查看右侧会话中Sql语句执行情况的变化
2.2.4 查看右侧会话
被阻塞了,耗时 22.15 秒
2.2.5 右侧也执行提交
2.2.6 左侧查看结果
2.2.7 右侧查看结果
结果相同,且是符合预期。
2.2.8 分析&结论
在左侧的更新语句中,限制了 id 范围为 [1, 3],Mysql在执行的时候,就会把范围内的所有符合条件的 id(对于本例就是 1, 2, 3)所对应的更新操作锁住,从而使得插入 id=2 的记录被阻塞。
3 结论
主键范围查询时,注意间隙锁