往同一个空间隙里并发插入不同的值,再对比这个间隙已经被别人持有Gap Lock的情况,看插入意向锁真实的冲突边界在哪。
accounts的id=30和id=40之间是空的,(30,40)这个间隙里可以插入任意32~39的新id。
代码-- 场景一:两个会话真实同时往同一个间隙里插入不同的值 session C: INSERT INTO accounts VALUES (32, 1000, 32); session D: INSERT INTO accounts VALUES (37, 1000, 37); -- 场景二:先有一个会话对这个间隙持有Gap Lock session E: SELECT * FROM accounts WHERE id BETWEEN 32 AND 38 FOR UPDATE; session F: INSERT INTO accounts VALUES (35, 1000, 35);
session C 插入id=32: 1461 微秒 (约1.46毫秒) session D 插入id=37: 1446 微秒 (约1.45毫秒) 两者几乎真实同时完成,没有谁等谁
C和D往同一个间隙(30,40)里插入不同的值,虽然都要先申请这个间隙的插入意向锁(Insert Intention Lock),但真实测出来两者耗时都在1.5毫秒左右,几乎同时完成,没有互相等待的迹象。插入意向锁真实是一种特殊的间隙锁,它和其他插入意向锁之间天然不冲突——只要两次插入真实落在间隙的不同位置,InnoDB允许它们并发进行。
E 先用 FOR UPDATE 拿到 (32,38) 范围的 Gap Lock F 尝试插入 id=35(真实落在E持有的间隙内部): ERROR 1205 (HY000): Lock wait timeout exceeded ← 真实被挡住
每一步都是本文上面用真实并发会话跑出来的原始结果。