[CMU 15-445] 18 基于时间戳的乐观并发协议

1. Overview

上一届介绍的2PL属于悲观的并发策略,事务的每一步操作都需要获得相应的锁才可以,大量的锁管理操作降低了事务处理性能。若本身负载中的不同事务发生读写冲突的概率很低甚至不会发生冲突的话,锁操作显得非常多余,等事务再执行过程中发生冲突时再终止就可以了,即一种乐观的并发控制思想。

本小节主要介绍基于时间戳的客观并发控制策略。

2. Basic Timestamp Ordering(T/O) Protocol

在基于时间戳并发控制协议中,每个事务都拥有一个唯一的时间戳标记,事务间并发执行的可串行化顺序必须与事务按照时间戳串行执行的效果一致。

在T/O中,事务不获取数据对象的读/写锁,每个数据对象X记录最近一次被写和读的时间戳,分别记为W-TS(X)和R-TS(X)。新事务在读写X时候根据W-TS(X)和R-TS(X)来判断:是否读了未来事务才会写的内容,是否覆写了未来事务读过的内容,是否覆写了未来事务已经写过的内容。

具体冲突情况如下,读冲突方面,判断事务Ti是否读了未来事务才会写的内容。如果冲突,将冲突的事务中止,重新赋予更大的时间戳重新执行。其中,T1本地需要拷贝一份X的值,这样确保X可以重复读(乐观并发思路是先预执行,随后再验证和提交)。

写冲突方面,判断是否覆写了未来事务读过的内容,是否覆写了未来事务已经写过的内容。

如下是一个T/O并发例子,其中假设T1的时间戳为1,T2的时间戳为2,即TS(T1)<TS(T2)。在执行过程中数据库根据R-TS、W-TS和TS判断是否发生了读写冲突。

T1和T2都已经执行完毕,未发生读写冲突,可以提交事务。

下面是一个检查出发生冲突的例子。T1的时间戳为1,T2的时间戳为2。第一步,事务T1写A,R-TS(A)<1,不冲突,可以直接读。

第二步,事务T2写A,W-TS(A)<1,不冲突,可以直接写入。

第三步,事务T1写A,W-TS(A)>1,发生冲突,A已经被未来发生的事务T2覆盖写入了新值,T1将被中止。

为了降低事务冲突率,T1在某些情况下可以不中止,只需要不执行此次操作即可,因为只要对于数据库而言最终的状态是相同的就行(有点像最终一致性的感觉)。若X已经被未来的事务读了,那么T1必须回滚,因为未来事务读到的是错误的值;若若X已经被未来的事务写了,那么数据库只需要忽略此次T1的写就可以。

使用 Basic T/O 并发控制协议可以避免死锁的发生,但是可能导致部分事务陷入饥饿(starvation),另外,也无法避免脏读的问题。

如下面的例子,若其中一个事务中止,调度是不可恢复的,即会发生脏读的问题。

2PL可以通过Strong Strict 2PL解决该问题,但是Basic T/O并发不行,因为T2已经早早的COMMIT了,没有锁机制来延迟它的提交。

3. Optimistic Concurrency Control(OCC)

乐观并发假设事务之间少有冲突发生,每个事务都有一个私有空间,事务将读到的内容临时存放在私有空间,随后对私有空间中的值做修改。当事务执行完后,数据库根据事务的时间戳和临时空间中的读写内容判断事务之间是否发生冲突,若没有发生冲突再将事务的所有修改写入数据库。

乐观并发协议分为三个阶段,分为Read、Validation、Write三个阶段。其中,Read阶段跟踪事务的每步的读集、写集放入私有空间;Validation阶段根据每个事务的私有空间内容检查事务是否冲突;Write阶段将事务的操作写入数据库或者中止它(事务的时间戳等到 Validation 阶段分配)。

在Validation阶段,验证的方法有两种,分别是前向验证(Backward Validation)以及后向验证(Forward Validation),但所有事务必须使用同一种验证策略。

前向验证是指与之前已经提交的事务进行比较。

后向验证是指与当前事务并发执行但还未提交的事务。

下面是一个OCC运行示例,T1和T2并发执行。

事务T2进入Validation阶段,T2被赋予时间戳1。

根据数据库当前状态发现事务T2未与其他事务冲突,将T2的修改写入数据库,事务T1继续向后执行。

事务T1进入Validation阶段并被赋予时间戳2,检查数据库当前状态发现未与其他事务发生冲突,直接写入数据库,更改数据库中A的值、Value和W-TS。

Validation阶段负责保证事务的并发调度满足可串行化性质。

以下是几种调度的Validation示例。在第一种调度中,事务T1先获得了时间戳,那么可串行化的效果必须是T1、T2。但是这里T2没有读到T1更改后的值(因为T1还没有WRITE),因此T1需要中止。

但若将T2的VALIDATE阶段提前,这样T2获得的时间戳小于T1,等价的串行化顺序应该是T2、T1,这时候下面的调度就是可串行化的调度。

4. Partition-based Timestamp Ordering

前面介绍的OCC策略存在的性能瓶颈包括:事务需要每次将读写内容存入本地私有空间,Validation、Write阶段的开销,事务的中止将带来比2PL更大的性能影响。

在Validation阶段,事务需要与之前所有提交的数据库状态做比对,这时候需要获取这些数据对象的锁,性能将受影响。

如果能够将互相冲突的事务分到不同的机器中处理,将数据水平划分,单个机器内无冲突事务那么性能将获得巨大提升(这不就是分布式数据库么,为了不冲突每个机器内的事务串行执行)。

抛开之前讨论的内容,到目前为止我们讨论的事务中只有Read和Update操作,没有Insert。当事务中出现了Insert操作时候,目前为止介绍的所有并发控制策略(包括2PL、OCC)都不能够保证最终调度的可串行化,可能出现下面的幻读问题。

因为T1的锁只能锁定表中当前的数据,不能锁定新插入的数据。

可以通过一些特殊的锁来解决这些问题,

5. Isolation Level

保证可串行化并发调度固然重要,但这同时也限制了并发性能。为了在可串行化与并发执行性能之间进行trade-off,DBMS允许使用不同的隔离级别,允许特殊情况下的读写不一致问题,释放系统性能。

隔离级别从强到弱依次分为:串行化、可重复读、读已提交、读未提交。

  • 串行化:调度完全符合串行化,满足可重复读、不出现脏读和幻读情况。
  • 可重复读:允许出现幻读。
  • 读已提交:允许出现幻读和不可重复读。
  • 读未提交:允许出现幻读和不可重复读以及脏读。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值