文章目录
并发控制的种类
- 基于锁的并发控制方式
- 基于回滚的并发控制方式
什么是时间戳
- 当一个事务启动的时候,系统赋予这个事务一个时间戳。
- 时间戳可以表征一个事务开始的时间,将一系列事务按照时间戳的顺序进行并发控制,可以不借助锁
时间戳并发控制的原理
- 借助时间戳,强制一组并发事务的交叉执行,等价于一个特定顺序 **(时间戳由小到大)**的串行执行
- 在运行的过程中判断是否存在 冲突,如果有冲突,就撤销整个事务,并且重启该事务,重新为整个事务分配时间戳(一个更加靠后的时间戳),如果没有冲突,就继续执行。
如何判定是否存在冲突
- 读-读操作之间不存在冲突
- 读-写操作之间可能存在冲突,当具有较小时间戳的事务(先执行的)先读,而具有较大时间戳的事务再写,这种情况下是不冲突的。但是如果相反, 存在较小时间戳的后读,较大时间戳的先写,就会出现 读-写冲突
- 写-写操作之间也存在冲突,如果较小时间戳事务先写,较大时间戳事务再写也没问题。相反也会存在冲突。
- 按照如上定义,三个事务的先后顺序应该是 T2, T3, T1。
- 从表中可以看出 T1 读 B 的操作是最先执行的,而其他事务中不存在写 B 的操作,因此 r 1 ( B ) r_1(B) r1(B) 和其他操作不存在冲突
- r 2 ( A ) r_2(A) r2(A) 是第二个执行的,后面也存在 W 1 ( A ) , W 3 ( A ) W_1(A), W_3(A) W1(A),W3(A) 是对 A 进行写操作,但这两个写操作都在 r 2 ( A ) r2(A) r2(A) 之后,因此不存在冲突。
- r 3 ( C ) r_3(C) r3(C) 对 C 进行读操作,同样对 C 进行操作的还有 W 2 ( C ) W_2(C) W2(C),按照时间戳 T2 事务应该发生在 T3 之前,因此 r 3 ( C ) r_3(C) r3(C) 和 W 2 ( C ) W_2(C) W2(C) 存在“读-写”冲突。
- W 1 ( B ) W_1(B) W1(B) 在 r 1 ( B ) r_1(B) r1(B) 之后,又是同一个事务,因此不存在冲突
- W 1 ( A ) W_1(A) W1(A) 是对 A 进行写操作,与此相同的是同样对 A 进行写操作的 W 3 ( A ) W_3(A) W3(A) 但是根据上面的时间戳顺序,T3 应该先于 T1 进行写操作,因此 W 1 ( A ) W_1(A) W1(A) 和 W 3 ( A ) W_3(A) W3(A) 存在 “写-写” 冲突
基于时间戳的调度规则
1. 保留对数据元素操作的最大时间戳
- R T ( X ) RT(X) RT(X):进行读数据 X 所涉及的最大的时间戳
- W T ( X ) WT(X) WT(X):进行写数据 X 所涉及的最大的时间戳
- T S ( T ) TS(T) TS(T):某个事务 T 的时间戳
以上图的例子:
- R T ( A ) = r 2 ( A ) = 150 RT(A)=r_2(A)=150 RT(A)=r2(A)=150
- R T ( B ) = r 1 ( B ) = 200 RT(B)=r_1(B)=200 RT(B)=r1(B)=200
- R T ( C ) = r 3 ( C ) = 175 RT(C)=r_3(C)=175 RT(C)=r3(C)=175
- W T ( A ) = W 1 ( A ) = 200 WT(A)=W_1(A)=200 WT(A)=W1(A)=200
- W T ( B ) = W 1 ( B ) = 200 WT(B)=W_1(B)=200 WT(B)=W1(B)=200
-
W
T
(
C
)
=
W
2
(
C
)
=
150
WT(C)=W_2(C)=150
WT(C)=W2(C)=150
2. 判断并处理 读-写,写-读,写-写冲突
读-写冲突处理
- 若事务 T T T 读数据 X,那么将 T 的时间戳 T S TS TS 与 W T ( X ) WT(X) WT(X) 比较:
- 如果 T S TS TS 数值大,那么允许 T 进行操作,并且更改 R T ( X ) RT(X) RT(X) 为 m a x { R T ( X ) , T S } max\{RT(X), TS\} max{RT(X),TS}
- 如果 T S TS TS 小,代表有冲突存在,那么撤回整个 T 并重启 T。
写-读冲突处理
- 若事务 T T T 写数据 X,那么将 T 的时间戳 T S TS TS 与 R T ( X ) RT(X) RT(X) 比较:
- 如果 T S TS TS 数值大,那么允许 T 进行操作,并且更改 W T ( X ) WT(X) WT(X) 为 m a x { W T ( X ) , T S } max\{WT(X), TS\} max{WT(X),TS}
- 如果 T S TS TS 小,代表有冲突存在,那么撤回整个 T 并重启 T。
写-写冲突处理
- 若事务 T T T 写数据 X,那么将 T 的时间戳 T S TS TS 与 W T ( X ) WT(X) WT(X) 比较:
- 如果 T S TS TS 数值大,那么允许 T 进行操作,并且更改 W T ( X ) WT(X) WT(X) 为 T 的时间戳。
- 如果 T S TS TS 小,代表有冲突存在,那么撤回整个 T 并重启 T。
3. 实例
- 初始化 A, B, C 对应的读写操作的时间戳都是 0,
- 发生了 r 1 ( B ) r_1(B) r1(B) 那么将 RT(B) 的时间戳改为 200,以此类推一直到 W 1 ( A ) W_1(A) W1(A) 更新时间戳都没有冲突
- 当更新 W 2 ( C ) W_2(C) W2(C) 时,可以发现,如果要进行此操作, T S ( T 2 ) = 150 TS(T_2)=150 TS(T2)=150 但是 R T ( C ) = 200 RT(C)=200 RT(C)=200 此时, T S ( T 2 ) < R T ( C ) TS(T_2)<RT(C) TS(T2)<RT(C) 因此,代表一个后发生的事务先读了 C, 然后才由 T2 写 C,这产生了冲突,因此为了维护不产生混乱, T2 应该整个撤销,重启。