隔离性:看不见的读写冲突,要怎么处理

209 阅读2分钟

image.png

因为时间误差存在,2-C 时间点附近会形成一个不确定时间窗口,也称为置信区间或可信区间。同样,T6-S 也只是一个时间窗口。时间误差不能消除,但可以通过工程方式控制在一定范围内,例如在 Spanner 中这个不确定时间窗口(记为ɛ)最大不超过 7 毫秒,平均是 4 毫秒。

解决方法有两种方式可供选择,分别是写等待和读等待。

写等待

Spanner 选择了写等待方式,更准确地说是用提交等待(commit-wait)来消除不确定性。

对于一个绝对时间点 S,什么时候 TT.after(S) 为真呢?至少需要等到 S + ɛ时刻才可以,这个ɛ就是我们前面说的不确定时间窗口的宽度。其中 TT.after() 用于判断当前时间是否晚于指定时间。

image.png

Ta 在 S 时刻写盘,保存的时间戳也是 S。事务 Tb 在 Ta 结束后的 S+X 时刻启动,获得时间区间的最小值是 TT1.earliest。如果 X 小于时间区间ɛ,则 TT1.earliest 就会小于 S,那么 Tb 就无法读取到 Ta 写入的数据。Tb 在 Ta 提交后启动却读取不到 Ta 写入的数据,这显然不符合线性一致性的要求。

image.png

事务 Ta 在获得“提交时间戳”S 后,再等待ɛ时间后才写盘并提交事务。真正的提交时间是晚于“提交时间戳”的,中间这段时间就是等待。这样 Tb 事务启动后,能够得到的最早时间 TT2.earliet 肯定不会早于 S 时刻,所以 Tb 就一定能够读取到 Ta。这样就符合线性一致性的要求了。

适用误差很小的系统,Spanner 能够将时间误差控制在 7 毫秒以内。

读等待:CockroachDB

读等待只在特殊条件下才被触发,影响的范围要小得多。

image.png

遇到有关联事务时,存在不确定的时间窗口,读操作的事务通过重启得到新的时间戳,以超过不确定时间窗口。

在这个过程中,可以看到读等待的两个特点:一是偶发,只有当读操作与已提交事务间隔小于设置的时间误差时才会发生;二是等待时间的更长,因为事务在重启后可能落入下一个不确定时间窗口,所以也许需要经过多次重启。

读等待适用于误差更大的系统,CockroachDB 对误差的预期达到 250 毫秒。


此文章为6月Day13学习笔记,内容来源于极客时间《分布式数据库30讲》