引言
在快照隔离系统中,每个事务似乎都在数据库的独立、一致的快照上进行操作。其更改在提交时间之前仅对该事务可见,提交时间之后,所有更改将以原子方式对稍后开始的任何事务可见。如果事务 T1 修改了对象x,而另一个事务 T2在 T1的快照开始之后、T1提交之前提交了对x的写入 ,则 T1必须中止。
快照隔离是一种事务模型:操作(通常称为"事务")可能涉及按顺序执行的多个基本子操作。它还具有多对象属性:操作可以作用于系统中的多个对象。
快照隔离无法完全可用;在存在网络分区的情况下,部分或所有节点可能无法取得进展。为了实现完全可用性,常允许以长分叉异为代价,请考虑并行快照隔离,或(较弱但更受支持的)读取已提交。
与强制事务完全排序的可序列化性不同,快照隔离仅强制部分排序:一个事务中的子操作可能与其他事务中的子操作交错。快照隔离允许的最显着现象是写入偏差,它允许事务读取重叠状态,修改不相交的对象集,然后提交;以及只读事务异常,涉及部分不相交的写入集。
快照隔离意味着读取已提交。但是,它不施加任何实时约束。如果进程 A 完成写入w,则进程 B 开始读取r,但不一定保证r观察到w。与提供全序和实时保证的严格可序列化性相比,某些数据库提供快照隔离的实时变体。
此外,快照隔离不需要事务之间按进程排序。进程可以观察到写入,然后在后续事务中又无法观察到相同的写入。事实上如果这些写入发生在不同的事务中,进程可能无法观察到哪怕是自己的先前写入。为了强制同一进程中的事务按顺序执行,请考虑前缀一致的快照隔离。
快照隔离的广义形式允许病态排序。例如,快照隔离数据库可以始终为任何读取返回空状态,方法是看起来在时间 T0 执行这些读取。它还可以通过重新排序只写事务以在任何读取之后在历史记录的最后执行来丢弃只写事务。假设从未观察到增量的结果,也可以丢弃增量之类的操作。幸运的是,大多数实现并未这样做。
一系列快照隔离
论文对快照隔离允许的历史记录的限制程度各不相同。Berenson等人的原始论文对提交和开始时间戳与挂钟时间之间的关系有些含糊,而 Daudjee & Salem 的后续工作建立了 "经典/强"和"广义/弱" SI 级别。Adya 对 SI 的形式化假设我们将调度程序做出的特定选择视为既定事实:历史记录是否为 SI 取决于调度程序的操作。这会产生一系列可能的快照隔离,具体取决于调度程序的实现方式。
如果将 SI 解释为强制事务始终选择高于每个已提交事务的提交时间的开始时间,那么快照隔离显然与可序列化无法比拟:它强制执行可序列化所不具备的实时顺序。
在与 Bailis、Crooks、Fekete、Hellerstein、Sutra 和 Shapiro 进行广泛交流后,Jepsen 以更宽松的方式解释了快照隔离:我们采用 SI 来禁止包含多个相邻读写反依赖边的事务之间的依赖循环。根据这个广义的定义,快照隔离严格弱于可序列化性。此定义与更广泛的实现兼容。
参考
Berenson、Bernstein 等人首先根据抽象算法定义了快照隔离:
每个事务都会从事务启动时的(已提交)数据快照(称为"开始时间戳")中读取数据。此时间可以是事务首次读取之前的任何时间。只要可以维护来自其开始时间戳的快照数据,在快照隔离中运行的事务就永远不会被阻止尝试读取。事务的写入(更新、插入和删除)也将反映在此快照中,如果事务第二次访问(即读取或更新)数据,则将再次读取。事务开始时间戳之后活动的其他事务的更新对于事务是不可见的。
当事务 T1时刻 准备提交时,它会获得一个 Commit-Timestamp,该时间戳大于任何现有的 Start-Timestamp 或 Commit-Timestamp。
仅当 T1 的执行间隔 [StartTimestamp, Commit-Timestamp] 内没有其他事务 T2 写入 T1 也写入的数据时,事务才会成功提交。否则,T1 将中止。
此功能称为 First-committer-wins,可防止丢失更新(现象 P4)。当 T1 提交时,其更改对所有 Start-Timestamp 大于 T1 的 Commit-Timestamp 的事务都可见。
为了获得每个流程的订单或实时订单,我们可以对开始和提交时间戳添加约束。
有关基于抽象执行的合理直观的形式化,请参阅 Cerone、Bernardi 和 Gotsman 的论文 《具有原子可见性的事务一致性模型框架》,其中将快照隔离指定为四个属性的组合:
-
1)内部一致性:在事务中,读取会观察该事务最近的写入(如果有)
-
2)外部一致性:事务 T1中没有先前写入的读取必须遵守事务 T0 写入的状态,使得 T0对于 T1可见,并且没有最近的事务写入该对象。
-
3)prefix:交易以相同的顺序对所有节点可见
-
4)NoConflict:如果两个事务写入同一个对象,则一个事务必须对另一个事务可见。
对于基于状态的形式化,请参阅 Crooks、Pu、Alvisi 和 Clement:眼见为实:以客户端为中心的数据库隔离规范。
备注
本篇可能有些拗口以及难于理解,如果有疑问,欢迎大家留言,我将不定期跟大家讨论答疑。
原创不易,这个系列尽量拆成比较简短的话题,方便大家理解单一知识点,希望大家价值,你们的点赞关注转发是我持续下去的动力。
感谢!