封锁就是事务T在对某个数据对象(例如表、记录等)操作之前,先向系统发出请求,对其加锁。加锁后事务T就对该数据对象有了一定的控制,在事务T释放它的锁之前,其它的事务不能更新此数据对象。
封锁是实现并发控制的一个非常重要的技术
7.3.2.1 封锁类型
DBMS通常提供了多种类型的封锁。一个事务对某个数据对象加锁后究竟拥有什么样的控制是由封锁的类型决定的。
基本封锁类型
排它锁(记为X锁)
共享锁(记为S锁)
封锁类型(续)
排它锁
排它锁又称为写锁。
若事务T 对数据对象A 加上X 锁,则只允许T 读取和修改A , 其它任何事务都不能再对A 加任何类型的锁,直到T 释放A 上的锁。
封锁类型(续)
共享锁
共享锁又称为读锁。
若事务T 对数据对象A 加上S 锁,则其它事务只能再对A 加S 锁,而不能加X 锁,直到T 释放A 上的S 锁。
封锁类型(续)
7.3.2.2 封锁粒度
X锁和S锁都是加在某一个数据对象上的。
封锁的对象可以是逻辑单元,也可以是物理单元。
逻辑单元: 属性值、属性值集合、元组、关系、索引项、整个索引、整个数据库等
物理单元:页(数据页或索引页)、块等
封锁粒度(续)
封锁对象可以很大也可以很小
例: 对整个数据库加锁
对某个属性值加锁
封锁对象的大小称为封锁的粒度
封锁粒度(续)
封锁的粒度越大,系统中能够被封锁的对象就越少,并发度也就越小,但系统开销也越小;
封锁的粒度越小,并发度越高,但开销也就越大。
选择封锁粒度时必须同时考虑开销和并发度两个因素,进行权衡,以求得最优的效果。
封锁粒度(续)
一般原则
需要处理大量元组的用户事务:以关系为封锁单元;
需要处理多个关系的大量元组的用户事务:以数据库为封锁单位;
只处理少量元组的用户事务:以元组为封锁单位
7.3.2.3 封锁协议
什么是封锁协议
对数据对象加锁时,需要约定一些规则。
何时申请X锁或S锁
持锁时间
何时释放
两段锁协议
可串行性是并行调度正确性的唯一准则,两段锁协议就是为保证并行调度可串行性而提供的封锁协议。
两段锁协议的内容
1. 在对任何数据进行读、写操作之前,事务首先要获得对该数据的封锁
2. 在释放一个封锁之后,事务不再获得任何其他封锁。
两段锁协议(续)
例:
事务1的封锁序列:
Sck A ... Sck B ... Xck C ... Unck B ... Unck A ... Unck C;
事务2的封锁序列:
Sck A ... Unck A ... Sck B ... Xck C ... Unck C ... Unck B;
事务1遵守两段锁协议,而事务2不遵守两段协议。
两段锁协议(续)
并行执行的所有事务均遵守两段锁协议,则对这些事务的所有并行调度策略都是可串行化的。
所有遵守两段锁协议的事务,其并行执行的结果一定是正确的。
死锁
封锁技术可以有效地解决并行操作的一致性问题,但也带来死锁的问题
死锁
什么是死锁
T1 T2
死锁(续)
如何解决死锁
解决死锁的两类方法
1. 死锁的预防
2. 死锁的诊断与解除
死锁的预防(续)
预防死锁的方法
一次封锁法
顺序封锁法
(1)一次封锁法
一次封锁法要求每个事务必须一次将所有要使用的数据全部加锁,否则就不能继续执行。
一次封锁法存在的问题:降低并发度
扩大封锁范围
一次就将以后要用到的全部数据加锁,势必扩大了封锁的范围,从而降低了系统的并发度。
(2)顺序封锁法
顺序封锁法是预先对数据对象规定一个封锁顺序,所有事务都按这个顺序实行封锁。
顺序封锁法存在的问题
维护成本高
数据库系统中可封锁的数据对象极其众多,并且随数据的插入、删除等操作而不断地变化,要维护这样极多而且变化的资源的封锁顺序非常困难,成本很高。
死锁的预防(续)
结论
在操作系统中广为采用的预防死锁的策略并不很适合数据库的特点
DBMS 在解决死锁的问题上更普遍采用的是诊断并解除死锁的方法
2. 死锁的诊断与解除
方法
由DBMS的并发控制子系统定期检测系统中是否存在死锁,一旦检测到死锁,就要设法解除。
死锁的诊断与解除(续)
检测死锁
超时法
如果一个事务的等待时间超过了规定的时限,就认为发生了死锁。
优点
实现简单
缺点
有可能误判死锁
时限若设置得太长,死锁发生后不能及时发现
死锁的诊断与解除(续)
解除死锁
选择一个处理死锁代价最小的事务,将其撤消,释放此事务持有的所有的锁,使其它事务能继续运行下去。