简介
封锁是实现并发控制的一个非常重要的技术。
DBMS通常提供了多种类型的封锁。
一个事务对某个数据对象加锁后究竟拥有什么样的控制是由封锁的类型决定的。
类型
基本类型
排它锁(记为X锁)
共享锁(记为S锁)
排它锁
排它锁又称为写锁。
若事务T 对数据对象A 加上X 锁,则只允许T 读取和修改A ,其它任何事务都不能再对A 加任何类型的锁,直到T 释放A 上的锁。
共享锁
共享锁又称为读锁。
若事务T 对数据对象A 加上S 锁,则其它事务只能再对A 加S 锁,而不能加X 锁,直到T 释放A 上的S 锁。
X锁和S锁都是加在某一个数据对象上的。
对象
单元
封锁的对象可以是逻辑单元,也可以是物理单元。
逻辑单元: 属性值、属性值集合、元组、关系、索引项、整个索引、整个数据库等;
物理单元:页(数据页或索引页)、块等。
粒度
封锁对象可以很大也可以很小,例如对整个数据库加锁、对某个属性值加锁。
封锁对象的大小称为封锁的粒度。
封锁的粒度越大,系统中能够被封锁的对象就越少,并发度也就越小,但系统开销也越小;
封锁的粒度越小,并发度越高,但开销也就越大。
选择
选择封锁粒度时必须同时考虑开销和并发度两个因素,进行权衡,以求得最优的效果。
一般原则——
①需要处理大量元组的用户事务:以关系为封锁单元。
②需要处理多个关系的大量元组的用户事务:以数据库为封锁单位。
③只处理少量元组的用户事务:以元组为封锁单位。
协议
基本定义
封锁协议指对数据对象加锁时,需要约定的一些规则,包括:
①何时申请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不遵守两段协议。
并行执行的所有事务均遵守两段锁协议,则对这些事务的所有并行调度策略都是可串行化的。
所有遵守两段锁协议的事务,其并行执行的结果一定是正确的。
死锁
基本定义
封锁技术可以有效地解决并行操作的一致性问题,但也带来死锁的问题。
解决方法
解决死锁的两类方法
1. 死锁的预防
2. 死锁的诊断与解除
预防
预防死锁的方法:
(1)一次封锁法
一次封锁法要求每个事务必须一次将所有要使用的数据全部加锁,否则就不能继续执行。
一次封锁法存在的问题:降低并发度;扩大封锁范围。
一次就将以后要用到的全部数据加锁,势必扩大了封锁的范围,从而降低了系统的并发度。
(2)顺序封锁法
顺序封锁法是预先对数据对象规定一个封锁顺序,所有事务都按这个顺序实行封锁。
顺序封锁法存在的问题:维护成本高。
数据库系统中可封锁的数据对象极其众多,并且随数据的插入、删除等操作而不断地变化,要维护这样极多而且变化的资源的封锁顺序非常困难,成本很高。
评价:
在操作系统中广为采用的预防死锁的策略并不很适合数据库的特点。
DBMS 在解决死锁的问题上更普遍采用的是诊断并解除死锁的方法。