Skip to content

快照隔离

Snapshot isolation · SI

让事务读取开始时一致快照,并以先提交者获胜规则排除并发同项写入的隔离级别。

形式陈述

快照隔离(snapshot isolation, SI)为每个事务 T 分配开始时间戳 s(T);若提交成功,再分配提交时间戳 c(T)>s(T)。除读取自身写集外,T 的所有普通读取都来自同一个一致快照:对数据项 x,返回在 s(T) 之前已提交的最新版本,而不读取其他事务的未提交写。读视图在整个事务期间固定,不因并发提交而逐语句前移。

更新事务提交时执行 first-committer-wins 检查。若存在已提交事务 UT 时间区间重叠,且写集相交

[s(T),c(T))[s(U),c(U)),W(T)W(U),

则两者不能都提交;先通过提交点者获胜,另一方中止。更常见的实现表述是:T 若发现自 s(T) 以来已有并发事务提交了它也要写的数据项,就必须放弃提交。该规则排除并发事务对同一版本的 lost update,却不检查所有读写依赖。

SI 是一种事务历史语义,MVCC是实现它的常见机制。版本链、事务 ID 与垃圾回收并不自动构成 SI;系统还需保证快照在所有读取上对应同一逻辑时点,并在提交处原子执行写写冲突检查。相同 MVCC 基础也可实现其他隔离级别。

从依赖图看,SI 排除了含有并发写写冲突的已提交组合,但允许读写反依赖:事务 Ti 从快照读取旧版本,而并发 Tj 随后覆盖该数据项,可记边 TirwTj。两个或更多这类边可能形成环,使历史不满足可串行化。因此“每个事务都读到内部一致的数据库版本”并不推出“所有事务共同等价于某个串行顺序”。

直觉

SI 像为事务在开始时拍下一整套数据库底片。事务之后无论运行多久,都从这套底片读取,并把自己的修改叠在私有层上。提交时系统只阻止两个并发事务改动同一数据项;只读者通常无需挡住写者,更新者也不会改变已开始事务的视图。

这种设计消除了脏读和事务内视图跳变,也避免许多同项覆盖,却看不见跨多行约束。两个事务可能依据同一旧快照分别修改不同记录,各自都没有写写冲突,合起来却让业务不变量失效。

例子与边界

on_call(doctor, active) 初始有两行:医生 Alice 与 Bob 的 active 都为真,业务约束是至少一名医生值班。两个事务并发开始,并取得同一快照:

text
T_A: read Alice=true, Bob=true
     because Bob is active, write Alice=false

T_B: read Alice=true, Bob=true
     because Alice is active, write Bob=false

TA 的写集为 {Alice}TB 的写集为 {Bob},两者不相交,因此 first-committer-wins 不会中止任何一方。两笔事务都提交后,两行均为假,违反“至少一人值班”。历史中,TA 读取了 TB 后来覆盖的 Bob 旧版本,产生 TArwTBTB 对 Alice 的旧读产生反向边 TBrwTA,依赖环证明不存在等价串行顺序。

这不是 lost update。两笔事务写的是不同记录,没有任何一个写覆盖另一个写;异常来自分别读取对方将要改动的旧版本,再把两个决策组合起来。若强行把例子改成双方都写同一行,SI 会让后提交者中止,反而失去 write skew 的核心结构。

作为对照,两个事务并发修改同一医生记录,或争用同一个唯一座位。它们的写集相交,先提交者发布新版本,另一方在提交检查中发现冲突并中止。这说明 SI 确实解决一类冲突,只是保护单位停留在写项,没有自动覆盖跨行谓词。

推论与应用

快照隔离适合读多写少、长查询需要稳定视图的工作负载。它常能避免读写阻塞并提供比 read committed 更易理解的事务内观察,但系统文档必须明确快照形成时刻、并发定义、写冲突粒度以及唯一约束和谓词更新怎样处理;产品名称中的“snapshot”不保证完全采用经典 SI。

若应用需要可串行化,可在 SI 之上引入谓词锁、显式锁定关键汇总行,或使用 Serializable Snapshot Isolation 检测危险的读写反依赖结构并中止部分事务。SSI 是更强的并发控制策略,不应倒写进 SI 定义。SI 同样不自动提供外部一致性、持久性或分布式原子提交,这些性质需要独立协议。

参考资料
  • Hal Berenson et al., “A Critique of ANSI SQL Isolation Levels,” SIGMOD 1995, pp. 1–10。
  • Alan Fekete et al., “Making Snapshot Isolation Serializable,” ACM Transactions on Database Systems 30(2), 2005, pp. 492–528。
  • Michael J. Cahill, Uwe Röhm, and Alan D. Fekete, “Serializable Isolation for Snapshot Databases,” SIGMOD 2008, pp. 729–738。