引子
游标稳定性是一种一致性模型,它通过防止丢失更新来增强读取提交。它引入了游标的概念,游标指的是事务正在访问的特定对象。事务可能有多个游标。当事务使用游标读取对象时,该对象不能被任何其他事务修改,直到游标被释放或事务提交。
这可以防止丢失更新,我们假设一种场景:
事务 T1时刻读取、修改并写回对象x,但不同的事务 T2也在T1读取x之后更新 x —— 导致 T2的更新实际上丢失。
游标稳定性是一种事务模型:操作(通常称为“事务”)可以涉及按顺序执行的多个基本子操作。它也是一个多对象属性:操作可以作用于系统中的多个对象。
游标稳定性无法完全实现;在存在网络分区的情况下,部分或所有节点可能无法继续工作。若要实现完全可用性,则以允许丢失更新为代价,请考虑使用已提交读取。若要实现更强的级别,即确保读取的每个记录(而不是游标)的稳定性,请考虑使用可重复读取。
请注意,游标稳定性不施加任何实时约束。如果进程 A 完成写入w,则进程 B 开始读取r,但不一定保证r观察到w。对于提供实时约束的事务模型,请考虑严格的可序列化性。
此外,游标稳定性不需要事务之间按进程排序。进程可以观察到写入,然后在后续事务中无法观察到相同的写入。事实上,如果这些写入发生在不同的事务中,进程可能无法观察到其自己的先前写入。
正文
Adya 对事务隔离级别的形式化根据两种禁止现象来定义游标稳定性:
G1:见下文。
G-cursor(x):有向序列化图,限制为单个对象 x,包含反依赖循环和至少一个写依赖边。
G1 包含三种不允许的现象:
- G1a(中止读取):事务观察到被中止事务修改的对象(可能通过谓词)。直观地说,事务必须提交,我们才能读取它们。
- G1b(中间读取):事务观察到一个对象(可能通过谓词)被另一个事务修改,但该修改不是该事务对该对象的最终修改。直观地说,事务必须先完成 ,我们才能读取它们,
- G1c(循环信息流):事务的有向序列化图包含一个完全由依赖边组成的有向环。直观地说,如果事务 T 1受到 T 2的影响,则 T 2不会受到 T 1 的影响。
由于游标稳定性严格强于读取已提交,因此它也禁止了 ANSI 现象:
P0(脏写):w 1(x)…w 2(x)
P1(脏读):w 1(x)…r 2(x)
但允许:
P2(模糊读取):r 1(x)…w 2(x)
P3(幻影):r 1(P)…w 2(P 中的 y)
在这个符号中,w表示写入,r表示读取,下标表示执行该操作的事务。… 表示除提交或中止之外的一系列微操作。P 表示谓词。在未使用游标的情况下,可能会出现模糊读取。
备注
本篇可能有些拗口以及难于理解,如果有疑问,欢迎大家留言,我将不定期跟大家讨论答疑。
原创不易,这个系列尽量拆成比较简短的话题,方便大家理解单一知识点,希望大家价值,你们的点赞关注转发是我持续下去的动力。
感谢!