首页 理论教育乐观并发控制算法-分布式数据库技术应用案例

乐观并发控制算法-分布式数据库技术应用案例

【摘要】:前面讨论的并发控制算法都是悲观算法。反之,夭折该事务,并重新启动它。图9.7乐观事务的执行阶段可以设计一个基于封锁的乐观并发控制算法。不过原始乐观建议是基于时标序的。论文提出,事务冲突并不很频繁时,乐观算法的性能优于封锁算法的性能。乐观算法的一个主要缺点是存储开销较大。为了能够验证,乐观机制必须存储其他已终止事务的读集和写集。然而,减少了并发度,因为这仅让一个事务运行。

前面讨论的并发控制算法都是悲观算法。换言之,它们假设事务间的冲突发生是频繁的,所以不允许事务在存取数据项时有冲突事务对这个数据项执行存取操作。这可以简化为事务按验证(validation,V)、读(read,R)、计算(compute,C)、写(write,W)阶段执行(见图9.6)。

图9.6 悲观事务的执行阶段

反之,乐观算法将验证阶段放到写阶段前来做(见图9.7)。这样提交给乐观调度器的操作不会再延迟。每个事务的读(read)、计算(compute)和写(write)操作不会直接去更新实际的数据库。每个事务对数据项的更新在该数据项的副本上实施。验证阶段包含检验这些更新是否维持数据库的一致性。如果答案是肯定的,则将这些变化全局化(即写入实际数据库)。反之,夭折该事务,并重新启动它。

图9.7 乐观事务的执行阶段

可以设计一个基于封锁的乐观并发控制算法。不过原始乐观建议是基于时标序的。因此下面只介绍使用时标序的乐观方法。

这个算法是Kung和Robinson在1981年提出的。与保守的基于时标序的算法不同,这个算法不仅是乐观的,而且是通过指定时标序实现的。这里,时标只与事务有关,而与数据项无关,而且不是在事务启动时指定时标而是在验证阶段开始时赋予时标,原因是只在验证阶段才需要时标,过早指定时标可能会产生不必要的事务拒绝服务。

现在分析并发事务关系的一些可能状态,如图9.8所示。两个并发事务间的时序关系可以如图9.8(a)、(b)和(c)三种情况所示。图9.8(a)表示一个事务启动时,前一个事务已经结束。图9.8(b)表示一个事务在另一个事务的写阶段启动。图9.8(c)表示一个事务在另一个事务启动后启动,而且启动发生在前一个事务的写阶段之前。

图9.8 可能的执行场景(www.chuimin.cn)

每个事务Ti被原始节点的事务管理器划分为一系列子事务,每个子事务可以在多个节点执行。令Tij为Ti的一个子事务,在节点j执行。直到验证阶段为止,每个本地执行如图9.8所示。在验证开始时将时标赋给该事务,而它又将之赋给子事务。Tij的本地验证按如下规则实行,这些规则是互斥的。

规则1 如果对所有的事务Tk,其中,ts(Tk)<ts(Tij),Tk在Tij启动读阶段前已经完成写阶段,则验证成功,因为这时事务的执行是串行序的。

规则2 如果有一个事务Tk,使得ts(Tk)<ts(Tij),表示Tk在Tij进入读阶段前已完成写阶段,则wst(Tk)∩rst(Tij)=∅,验证成功。

规则3 如果有一个事务Tk,使得ts(Tk)<ts(Tij),表示Tk在Tij完成读阶段前已完成其读阶段,则wst(Tk)∩rst(Tij)=∅和wst(Tk)∩wst(Tij)=∅,验证成功。

规则1是清楚的,它说明事务是按时标序顺序执行的。规则2保证数据项在有些可能发生读/写冲突时检测出潜在冲突,由于它们的读/写集不相交,所以不存在冲突。规则3则讨论事务重叠更严重的情况。

乐观并发控制算法的优点在于它能提供更高的并发性。论文提出,事务冲突并不很频繁时,乐观算法的性能优于封锁算法的性能。乐观算法的一个主要缺点是存储开销较大。为了能够验证,乐观机制必须存储其他已终止事务的读集和写集。特别是,那些在事务Tij到达节点j时正在处理的已终止事务的读集和写集必须存放起来,以便验证Tij。这样就增加了存储开销。

另一个问题称为饥饿(starvation)问题。细节请参阅参考文献[6]。

我们来看一个事务在其验证阶段失败的情况。接下来再试探一次,可能验证时还是失败。

当然,可以通过允许在一系列尝试失败后让该事务排外地存取数据库来解决问题。然而,减少了并发度,因为这仅让一个事务运行。