知识卡片
谓词锁与索引范围锁用近似换取幻读防护的性能可行性
内容
两阶段锁定要真正防住[[幻读导致写偏差的通用模式及物化冲突这个最后手段]],理论上需要 谓词锁:不同于挂在某一行上的普通共享/排它锁,谓词锁挂在”所有满足某个搜索条件的 对象”这个抽象集合上——包括数据库里现在还不存在、但将来可能插入进来、恰好会匹配 这个条件的对象(幻象)。规则是:事务A想按条件读取时要先获取该条件上的共享谓词锁, 如果事务B已经持有覆盖该条件的排它锁则A要等待;事务A想插入/更新/删除任何对象时, 必须先检查这个对象的旧值或新值是否落在别人持有的谓词锁范围内,若是则要等对方提交 或中止。这套机制理论上完美但性能极差——如果活跃事务持有大量谓词锁,每次操作都要 逐一检查是否匹配,开销随锁数量线性膨胀。实用的折衷是索引范围锁(也叫间隙锁):不 精确匹配谓词,而是把谓词近似成一个更大的、能挂在现有索引结构上的范围(比如把”12点 到1点预订123号房间”近似成”锁住123号房间在索引上的所有时段”,或者”锁住整个12-13点 时段的所有房间”)——只要这个更松的近似范围完全覆盖原始谓词,任何真正会违反原谓词 的写入也一定会撞上这个更大的锁范围,因此依然安全,只是可能不必要地多锁住一些原本 不冲突的操作。这个近似换来的收益是:可以直接挂在已有的索引项或索引区间上,不需要 额外维护一份独立的谓词锁数据结构,开销大幅降低;如果连能挂靠的索引都没有,数据库 只能退化到给整张表加共享锁,安全但会拖累所有并发写入,是性能最差的兜底方案。
参考来源
- 位置:《数据密集型应用系统设计》第七章《事务》"谓词锁""索引范围锁"(源文件:
_epub-src/ch7_split_005.html)
- 结论依据:原文定义谓词锁挂在满足搜索条件的所有对象(含幻象)上但性能不佳,
说明索引范围锁通过把谓词近似成挂在索引项/区间上的更大范围来降低开销,若无
可用索引则退化为整表共享锁,直接支撑本卡片结论。
- 原始内容:谓词锁限制访问……这里的关键思想是,谓词锁甚至适用于数据库中尚不
存在,但将来可能会添加的对象(幻象)……不幸谓词锁性能不佳……通过使谓词匹配
到一个更大的集合来简化谓词锁是安全的……如果没有可以挂载间隙锁的索引,数据库
可以退化到使用整个表上的共享锁。