Skip to content

交付一份快照验证与拒绝证书 ​

快照读取与提交验证路线的终点是一份可以重新执行的事务记录。它不能只有最终键值:相同最终值可能掩盖不同读来源,提交失败也可能来自写写冲突、旧读失效或保守危险结构。报告须把这些决定分开。

下载标准库核验器。普通运行与 python -O 都使用显式条件检查,任何错误抛出异常;程序不连接数据库、不请求网络、不在后台发送请求,也不把有限输入通过当成真实数据库认证。

一、冻结对象与观察 ​

使用固定键域0..15;键0表示x,键1表示y,值 None 表示不存在。初始版本的创建者为专用初始标识,提交序号为0。每次开始与提交尝试取得唯一递增边界序号;普通读、私有写可以夹在这些边界之间。

每笔事务记录开始序号、外部读的键/来源创建者/版本序号/数值、私有最终写,以及提交或中止结果。读取自己已经写过的值来自私有层;如果先前曾外部读过这个键,那份外部依据不能因后来写入而被删掉。

事务执行假设输入已经冻结、计算只影响私有状态。提交前不得把查询结果作为不可撤销响应,也不得发送外部业务副作用。附件展示并发控制,不负责网络调用幂等、掉电恢复或日志持久化。

二、同一份写偏差输入交给三种入口 ​

初始x=y=1。A在边界1开始,读到两个初始版本,准备x=0;B在边界2开始,读到同一快照,准备y=0。两个业务程序都以“另一个值仍为1”为允许关闭自身的前提。让A在边界3先提交,再让B在边界4尝试。

  • SI:两写集互斥,A、B都提交,最终x=y=0。图有A→rw(y) B及B→rw(x) A,找不到串行见证
  • OCC:A验证通过;B在键x发现当前版本由A在3发布,晚于B的开始2,提交被拒绝。证书须列旧来源0和新来源A,不能只写“版本不同”
  • SSI:B候选加入后,取I=A、pivot=B、O=A。两条并发rw边形成危险结构,O与I允许是同一事务;A先于B提交,过滤条件保留这份证书,所以B被拒绝

在两个拒绝分支,令B以新身份重新开始。它的新快照读到x=0,于是不再写y=0,成功完成后最终x=0、y=1。若仍重发旧W,就没有重跑条件判断,不能算安全重试。

报告应列“两个事务都成功”“一笔中止后重试”等真实结局,不把SI分支违反业务约束的预期结果删掉或改成通过同一安全断言。

三、把只读事务放进三环 ​

换成初态x=y=0,按下表执行:

边界 操作
1 P开始并读y的初始版本
2 Q开始,私有写y=1
3 Q提交
4 R开始,读x=0以及Q的y=1
5 只读R提交
6 P尝试发布x=1

在SI下三者都提交。交付版本链x₀→xP、y₀→yQ,随后按多版本依赖图逐条还原:

  • P读y₀,Q发布后续版本,给P→rw(y) Q
  • R读x₀,P发布后续版本,给R→rw(x) P
  • R读到Q版本,给Q→wr(y) R

串行要求是Q在R前、R在P前、P在Q前。实际提交顺序Q、R、P不能替代这份依赖推理;P的x私有副本也从未成为R的来源。

SSI在边界6重建完整历史,取得I=R、pivot=P、O=Q。两端并发条件分别为R/P、P/Q,Q的提交3早于R快照4,也早于R和P的提交5、6。因此当前P可以中止,已经提交的Q、R保持原决定。

刻意把R的记录在边界5丢弃,再进行同一次验证:R→P这条边会消失。这说明读者提交后其证据仍可能被并发写者需要,不应沿用普通共享锁“提交就释放”的清理直觉。

四、让结构仍在,却没有环 ​

只改一个动作:R不再读取y。开始、提交和其余读写全部不变。图中Q→R消失,剩下R→P→Q,其拓扑序R、P、Q保持所有读来源和版本次序。

SSI参考器仍会在P提交时找到同一双边链,提交次序和只读过滤也都通过,所以仍可能拒绝。它保护安全,却不是“恰好所有不可串行历史才中止”的判定器。需要交出这个合法串行顺序,作为误拒绝的证据,不能把没有查到返回路径写成已有环。

进一步迁移:去掉R,只运行P和Q。剩下一条P→rw Q,没有危险结构;SSI可接受两者并按P、Q解释。本页OCC却要求提交顺序Q、P,P的旧读y失效,所以会中止。两协议允许的并发历史不同,并非其中一方一定少做了检查。

五、三份接口反例 ​

验证与发布之间不能留空窗 ​

让A、B都在任何发布前检查完各自读集。两次检查都返回真,再分别发布x=0、y=0,最终约束失败。附件明确构造这一错误分支;正确入口应将检查与全部发布绑定成一个原子事件,或者另外加入有证明的并行验证机制。

盲写和读后更新不同 ​

C、D并发开始,都不读x,分别盲写7和9。OCC读集为空,可按C、D提交顺序都接受,最终x=9;SI及本SSI入口按first-committer-wins只接受C,最终x=7。若把C、D改成读x后加一,就必须增加外部读集合,不能继续按盲写分支接受。

空查询不能省成空读集 ​

在只有键8和15存在的场景中,考虑[10,13)为空后分别插11、12。扫描必须读取10、11、12的缺失版本,之后并发插入才能触发OCC旧读证书或SSI反依赖。

附件直接取全空数据库运行这个区间反例:两者读到空,SI双提交,而OCC/SSI拒绝后一个。读集应打印为三个键;若错误地只收集返回行,它会为空,两种后加检查便都失去所需输入。

六、安全只读快照的时序迁移 ​

先开始一个明确只读的R,且当时没有活跃更新者。R读旧x;随后才开始P、Q,让P读旧y、Q发布y,再让P发布x,最后R提交。图可能有R→rw P→rw Q,但Q在R快照之后才提交,不满足只读危险结构的必要时序,因此这一链不能让参考器拒绝R。

与第三节对照,那里P在R开始之前已经活跃,并且有指向R快照之前Q的反依赖,不能提前宣称R安全。是否安全看的是完整的并发者与提交时点,不是R有没有执行UPDATE。

若要在开始时免除跟踪,只读承诺必须由接口强制执行;普通事务“当前还没写”不能借此豁免后再写。附件保守地始终记录读集,在提交时才利用已知W为空的事实过滤,不实现提前免跟踪的生产优化。

七、交付清单与复算方法 ​

运行输出保留主轨迹、拒绝证书、重试与最终值。自查还应完成:

  1. 在三事务、两键的有限读写集合和边界次序中,独立枚举串行顺序,以读取来源与每键写者顺序直接核图的无环判据
  2. 对每份被SI接受的有环历史,找到满足并发、最早提交和只读过滤的危险结构;同时保留无环但仍有结构的实例计数
  3. 对SSI每一个接受前缀核无环和无合格危险结构,不能只检查最终数据库
  4. 对OCC的交错读写、盲写、删除及重试,按成功提交次序重新核所有外部读来源
  5. 保留普通和优化模式的实际结果;源码使用显式检查,二者必须字节一致

这些有限核验补充三个一般证明:版本图与固定版本序串行见证的等价、OCC的提交序归纳、SI环的相邻并发rw结构。它们没有覆盖任意SQL谓词、真实多核原子发布、有限内存回收或故障恢复,报告中应把这些尚未实现的接口留在边界之内。