DBMS - 并发控制
在可以同时执行多个事务的多道程序环境中,控制事务的并发性非常重要。 我们有并发控制协议来确保并发事务的原子性、隔离性和可序列化性。 并发控制协议大致可以分为两类 −
- 基于锁的协议
- 基于时间戳的协议
基于锁的协议
配备基于锁的协议的数据库系统使用一种机制,通过该机制,任何事务在获得适当的锁之前都无法读取或写入数据。 锁有两种 −
二进制锁 − 数据项上的锁可以处于两种状态; 它要么被锁定,要么被解锁。
共享/独占 − 这种类型的锁定机制根据其用途区分锁。 如果在数据项上获取锁以执行写操作,则它是排他锁。 允许多个事务写入同一数据项会导致数据库进入不一致状态。 读取锁是共享的,因为没有数据值被更改。
有四种类型的锁定协议可用 −
简单锁协议
简单的基于锁的协议允许事务在执行"写"操作之前获得每个对象的锁。 事务可能会在完成"写入"操作后解锁数据项。
预声明锁协议
预声明协议会评估其操作并创建需要锁定的数据项列表。 在开始执行之前,事务预先向系统请求它需要的所有锁。 如果所有的锁都被授予,则事务执行并在其所有操作结束时释放所有锁。 如果未授予所有锁,则事务回滚并等待直到授予所有锁。
![Pre-claiming 预认领](https://www.w3ccoo.com/dbms/images/pre_claiming.png)
两相锁定 2PL
此锁定协议将事务的执行阶段分为三个部分。 在第一部分中,当事务开始执行时,它会为其所需的锁寻求许可。 第二部分是事务获取所有锁的地方。 一旦事务释放了它的第一个锁,第三阶段就开始了。 在这个阶段,事务不能要求任何新的锁; 它只释放获取的锁。
![Two Phase Locking 两相锁定](https://www.w3ccoo.com/dbms/images/2PL.png)
两阶段锁有两个阶段,一个是增长,所有的锁都被事务获取; 第二阶段是收缩,事务持有的锁被释放。
要申请排他(写)锁,事务必须首先获取共享(读)锁,然后将其升级为排他锁。
严格的两相锁定
Strict-2PL 的第一阶段与 2PL 相同。 在第一阶段获得所有锁后,事务继续正常执行。 但与 2PL 相比,Strict-2PL 在使用后不会释放锁。 Strict-2PL 持有所有锁直到提交点,并一次释放所有锁。
![Strict Two Phase Locking 严格的两相锁定](https://www.w3ccoo.com/dbms/images/strict_2PL.png)
Strict-2PL 没有像 2PL 那样的级联中止。
基于时间戳的协议
最常用的并发协议是基于时间戳的协议。 该协议使用系统时间或逻辑计数器作为时间戳。
基于锁的协议在执行时管理事务之间冲突对之间的顺序,而基于时间戳的协议在事务创建后立即开始工作。
每个事务都有一个与之关联的时间戳,并且排序由事务的年龄决定。 在 0002 时钟时间创建的事务将比它之后的所有其他事务更早。 例如,任何在 0004 进入系统的事务 'y' 都会年轻两秒,并且优先级将给予较早的事务。
此外,每个数据项都被赋予了最新的读写时间戳。 这让系统知道对数据项执行最后一次"读取和写入"操作的时间。
时间戳排序协议
时间戳排序协议可确保事务在其冲突的读写操作中的可串行化。 这是协议系统的责任,应该根据事务的时间戳值执行冲突的任务对。
- 事务Ti的时间戳记为TS(Ti)。
- 数据项 X 的读取时间戳记为 R-timestamp(X)。
- 数据项 X 的写入时间戳记为 W-timestamp(X)。
时间戳排序协议的工作原理如下 −
如果事务 Ti 发出 read(X) 操作 −
- 如果 TS(Ti) < W-timestamp(X)
- 操作被拒绝。
- 如果 TS(Ti) >= W-timestamp(X)
- 已执行操作。
- 所有数据项时间戳已更新。
如果事务 Ti 发出 write(X) 操作 −
- 如果 TS(Ti) < R-timestamp(X)
- 操作被拒绝。
- 如果 TS(Ti) < W-timestamp(X)
- 操作被拒绝,Ti 回滚。
- 否则,执行操作。
Thomas 托马斯的写规则
该规则规定如果 TS(Ti) < W-timestamp(X),则操作被拒绝,Ti被回滚。
可以修改时间戳排序规则以使调度视图可序列化。
不是让 Ti 回滚,而是忽略"写入"操作本身。