相关资料来源于网络,侵删歉。
如果文章中存在错误,请下方评论告知我,谢谢!
DBMS对并行事务中各指令的安排执行(调度)是随机的,而不同的调度可能会产生不同的结果。
将所有事务串行执行的调度策略一定是正确的调度策略。 如果错了,一定是事务程序逻辑上的错误,不是因调度而产生的。
以不同的顺序串行执行事务也有可能会产生不同的结果,但由于不会将数据库置于不一致状态,所以都可以认为是正确的。
几个事务的并行执行是正确的,当且仅当其结果与按某一次序串行地执行它们时的结果相同(?)。当多个事务的一次并发执行效果与他们的某一种串行执行效果一样时,称这种并发调度策略为可串行化(Serializable)的调度。
并发事务对同一数据的读写次序是决定事务并发状态下是否正确的唯一因素。
判断能否可串行化的调度:
无论怎么移动冲突可交换指令,都无法与某一串行化调动等价,则不能可串行化调度。
如何保证并发操作的调度是正确的
为了保证并行操作的正确性,DBMS的并行控制机制必须提供一定的手段来保证调度是可串行化的。从理论上讲,在某一事务执行时禁止其他事务执行的调度策略一定是可串行化的调度,这也是最简单的调度策略,但这种方法实际上是不可行的,因为它使用户不能充分共享数据库资源。
保证并发操作调度正确性的方法
封锁方法:两段锁(Two-Phase Locking,简称2PL)协议
时标方法
乐观方法
并行执行的所有事务均遵守两段锁协议,则对这些事务的所有并行调度策略都是可串行化的。即:
(1)所有遵守两段锁协议的事务,其并行执行的结果一定是正确的。
(2)事务遵守两段锁协议是可串行化调度的充分条件,而不是必要条件。
(3)可串行化的调度中,不一定所有事务都必须符合两段锁协议。
两段锁协议与防止死锁的一次封锁法的比较:
一次封锁法要求每个事务必须一次将所有要使用的数据全部加锁,否则就不能继续执行,因此一次封锁法遵守两段锁协议;但是两段锁协议并不要求事务必须一次将所有要使用的数据全部加锁,因此遵守两段锁协议的事务可能发生死锁。
X锁和S锁都是加在某一个数据对象上的
封锁的对象:
逻辑单元:属性值、属性值集合、元组、关系、索引项、整个索引、整个数据库等
物理单元:页(数据页或索引页)、物理记录等
封锁对象可以很大也可以很小。例:对整个数据库加锁;对某个属性值加锁。
封锁对象的大小称为封锁的粒度(Granularity)
多粒度封锁(multiple granularity locking) 在一个系统中同时支持多种封锁粒度供不同的事务选择。
封锁的粒度 | 大 | 小 |
系统被封锁的对象个数 | 少 | 多 |
并发度 | 小 | 高 |
系统开销 | 小 | 大 |
选择封锁粒度
考虑封锁机构和并发度两个因素,对系统开销与并发度进行权衡。
需要处理多个关系的大量元组的用户事务:以数据库为封锁单位;
需要处理大量元组的用户事务:以关系为封锁单元;
只处理少量元组的用户事务:以元组为封锁单位。
多粒度树:以树形结构来表示多级封锁粒度,根结点是整个数据库,表示最大的数据粒度;叶结点表示最小的数据粒度。
多粒度封锁协议
允许多粒度树中的每个结点被独立地加锁
(1)对一个结点加锁意味着这个结点的所有后裔结点也被加以同样类型的锁
(2)在多粒度封锁中一个数据对象可能以两种方式封锁:显式封锁和隐式封锁
显式封锁:直接加到数据对象上的封锁
隐式封锁: 由于其上级结点加锁而使该数据对象加上了锁
显式封锁和隐式封锁的效果是一样的。