“消息传递中的崩溃使 2PC 依赖 write ahead log、幂等消息、超时与人工或启发式恢复。它协调数据库分片、消息系统和其他跨资源事务的 commit/abort,但不提供事务隔离;…”
形式陈述 ​
多版本并发控制(MVCC)不让更新原地抹去旧值,而是为键
其中 creator 标识创建事务,status 区分未提交、已提交与中止,begin/end 划定可见区间。事务
并另行允许
写操作创建新版本或私有写集,旧版本继续服务较早读视图;提交协议原子地决定事务的新版本何时对其他事务可见,中止则让这些版本永不进入公共视图。并发控制还必须处理写写冲突、唯一约束、谓词读和提交验证。MVCC 只提供“保存哪些版本、一次读选哪个版本”的机制框架,并不固定 read committed、快照读取或可串行化等某一种隔离语义。
正确性仍在事务历史上评价。这里的事务历史直接记录事务边界、读写事件、reads-from、提交与中止结果;它既不是只保留对象调用与返回的接口历史,也不要求收纳分布式执行的全部内部消息。可用多版本序列化图把事务作为顶点,并根据 reads-from、版本先后、写写冲突及读写反依赖建立边;图是否允许某个串行解释取决于系统承诺的可串行化版本。仅仅存在多个版本,不会自动让图无环。
旧版本也不能无限保留。垃圾回收需要计算仍可能被活跃读视图引用的低水位,只删除对所有允许未来读取都不可见的版本。长事务会固定很老的视图,使版本链和存储膨胀;强行回收则可能让仍合法的读无法重现其视图,因此保留策略是正确性与资源管理共同约束的组成部分。
直觉 ​
单版本系统像在同一张白板上反复擦写,读者与写者容易互相挡住。MVCC 更像给每次提交装订一页新版本:正在阅读旧版目录的事务可以继续翻自己的页,写者同时准备并发布新版。两者少了直接读写冲突,但系统必须准确回答“这个读者应该看到哪一页”。
版本数量只是手段,读视图与提交规则才决定隔离体验。同一套版本链可以支持每条语句重新取最新已提交值,也可以让整个事务固定视图,还可以配合序列化验证排除危险结构;因此 MVCC 与某个隔离级别不能互作同义词。
例子与边界 ​
报表事务
保存多版本仍可能产生不可串行化历史。两名值班医生分别读取“至少还有两人当班”,各自更新不同记录为休假;若机制只检测同一记录的写写冲突,两笔事务都可提交,结果无人值班。每次读都来自一致旧视图,版本链也完全有效,失败在于跨记录读写反依赖形成环。若目标是可串行化,系统还需谓词锁、SSI 式危险结构检测或其他验证。
“读者不阻塞写者”也不是无条件定律。读可能等待创建者事务提交以判断版本状态,DDL、唯一约束或缓存资源仍可能加锁;写者之间通常还要处理同键冲突。MVCC 缩小了一类读写互斥,并未消除所有阻塞和死锁来源。
推论与应用 ​
MVCC 把逻辑可见性与物理存储生命周期分开,使长查询、在线更新和时间点读取可以共享数据。实现审查应逐项核对版本标识、提交原子性、读视图形成时刻、冲突验证及回收低水位;只展示一条版本链不足以说明事务语义。
分布式数据库还要决定提交序号如何跨节点排序、事务原子提交怎样发布版本,以及故障恢复后未决版本如何处理。两阶段提交可以协调“全提交或全中止”,却不决定读视图或序列化顺序;原子提交与 MVCC 隔离是正交的协议层。
参考资料
- David P. Reed, Naming and Synchronization in a Decentralized Computer System, MIT PhD thesis, 1978。
- Philip A. Bernstein, Vassos Hadzilacos, and Nathan Goodman, Concurrency Control and Recovery in Database Systems, Addison-Wesley, 1987。
- Atul Adya, Weak Consistency: A Generalized Theory and Optimistic Implementations for Distributed Transactions, MIT PhD thesis, 1999。