一、思维导图
二、基础梳理
在数据库中为什么要并发控制?并发控制技术能保证事务的哪些特性?
- 数据库是共享资源,通常有许多个事务同时在运行。当多个事务并发地存取数据库时就会产生同时读取和/或修改同一数据的情况。若对并发操作不加控制就可能会存取和存储不正确的数据,破坏数据库的一致性。所以数据库管理系统必须提供并发控制机制。
- 并发控制可以保证事务的【一致性】和【隔离性】
并发操作可能会产生哪几类数据不一致?用什么方法能避免各种不一致的情况?
- 并发操作带来的数据不一致性包括三类
- 丢失修改(LostUpdate)
两个事务T1和T2读入同一数据并修改,T2提交的结果破坏了(覆盖了)T1提交的结果,导致T1的修改被丢失。
(发生在两个写事务间) - 不可重复读(Non-RepeatableRead)
不可重复读是指事务T1读取数据后,事务T2执行更新操作,使T1无法再现前一次读取结果。
不可重复读包括三种情况:- 事务T1读取某一数据后,事务T2对其做了修改,当事务T1再次读改数据时,得到与前一次不同的值
- 事务T1按一定条件从数据库中读取了某些数据记录后,事务T2删除了其中部分记录,当T1再次按相同条件读取数据时,发现某些记录消失了
- 事务T1按一条件从数据库中读取某些数据记录后,事务T2插入了一些记录,当T1再次按相同条件读取数据时,发现多了一些记录后两种不可重复读有时也称为幻影(phantom row)现象
(发生在读事务和更新事务间)
- 读“脏”数据(DirtyRead)
读“脏”数据是指事务T1修改某一数据,并将其写回磁盘,事务T2读取同一数据后,T1由于某种原因被撤销,这时T1已修改过的数据恢复原值,T2读到的数据就与数据库中的数据不一致,则T2读到的数据就为“脏”数据,即不正确的数据。
(发生在读和写事务间)
- 丢失修改(LostUpdate)
- 避免不一致性的方法和技术就是并发控制。并发控制的主要技术有封锁技术、时间戳方法、乐观控制方法、多版本并发控制方法等
什么是封锁?基本的封锁类型有几种?试述它们的含义。
- 封锁就是事务T在对某个数据对象例如表、记录等操作之前,先向系统发出请求,对其加锁。加锁后事务T就对该数据对象有了一定的控制,在事务T释放它的锁之前,其他的事务不能更新此数据对象。
- 基本的封锁类型有两种: 排它锁(简称X锁) 和共享锁(简称S锁)。
- 排它锁又称为写锁。若事务T对数据对象A加上X锁,则只允许T读取和修改A,其他任何事务都不能再对A加任何类型的锁,直到T释放A上的锁。这就保证了其他事务在T释放A上的锁之前不能再读取和修改A。
- 共享锁又称为读锁。若事务T对数据对象A加上S锁,则事务T可以读A但不能修改A,其他事务只能再对A加S锁,而不能加X锁,直到T释放A上的S锁。这就保证了其他事务可以读A,但在T释放A上的S锁之前不能对A做任何修改。
封锁协议
- 一级封锁协议:事务在修改数据R之前必须先对其加X锁,待事务结束才释放。
- 事务结束包括正常结束(COMMIT)和非正常结束(ROLLBACK)
- 一级封锁协议可防止丢失修改,可保证事务是可恢复的
- 一级封锁协议不能保证可重复读和脏数据(因为一级中,读而不写数据是不需要加锁的)
- 二级封锁协议:在一级封锁协议的基础上增加事务T在读取R之前必须先对其加S锁,读完释放S锁。
- 防止丢失修改,防止读脏数据
- 不能保证可重复读
- 三级封锁协议:在一级封锁协议的基础上增加事务T在读取R之前必须先对其加S锁,直到事务结束才释放S锁。
三级协议的主要区别在于什么操作需要申请封锁,以及何时释放锁(即持锁时间)
封锁协议级别越高,一致性程度越高
活锁和死锁
活锁
如果事务T1封锁了数据R,事务T2又请求封锁数据R,于是T2等待;T3也请求封锁数据R,当T1释放了R上的锁之后,系统首先批准了T3的请求,T2任然等待;然后T4又请求封锁R,当T3释放R上的锁之后,系统又批准了T4的请求……T2有可能永远等待,这就是活锁的情况。
- 避免活锁的简单方法是:采用先来先服务策略
死锁
如果事务T1封锁了数据R1,T2封锁了数据R2,然后T1又请求封锁R2,因T2封锁了R2,于是T1等待T2释放R2上的锁;接着T2又请求封锁R1,因T1封锁了R1,于是T2等待T1释放R1上的锁。这样就出现了T1在等待T2,而T2又在等待T1,的局面,T1、T2两个事务永远不能结束,形成死锁
- 解决死锁的方法:有两种思路
- 预防死锁的发生
① 一次封锁法:一次性将所有要使用的数据全部加锁,否则就不能继续执行
存在的问题:扩大了封锁范围,降低了系统的并发度;
② 顺序封锁法:预先对数据对象规定一个封锁顺序,所有事务都按照这个顺序实施封锁。
* 存在的问题:
1.数据库在动态地不断变化,要维护这样的资源的封锁顺序非常困难,成本很高。
2.事务的封锁请求可以随着事务的执行而动态地决定,很难实现确定每一个事务要封锁哪些对象,因此很难按规定的顺序去施加封锁。 - 死锁的诊断与解除(普遍采用的方法)
-
诊断
① 超时法:如果一个事务的等待时间超过了规定的时限,就认为发生了死锁- 存在的问题:
1.时间设置太短,有可能误判死锁
2.时间设置太长,死锁发生后不能及时发现
② 等待图法:事务等待图是一个有向图G=(T,U),T为结点的集合,每个结点表示正在运行的事务;U为边的集合,表示事务等待情况,若事务T1等待T2,则在T1、T2之间画一条有向边,从T1指向T2
- 存在的问题:
-
解除:常用方法是选择一个处理死锁代价最小的事务,将其撤销,释放此事务持有的所有的锁,使其他事务得以继续运行下去
-
- 预防死锁的发生
什么样的并发调度是正确的调度?
- 可串行化的调度是正确的调度。
- 可串行化的调度的定义:多个事务的并发执行是正确的,当且仅当其结果与按某一次序串行地执行它们时的结果相同,我们称这种调度策略为可串行化的调度。
试述串⾏调度和可串⾏化调度的区别?
-
串⾏调度 是多个事务按照⼀定的次序依次执⾏;在某⼀时刻只有⼀个事务在执⾏可串⾏化调度是并发调度中的⼀个概念。
-
在并发调度中,某⼀时刻有多个事务同时被处理。如果某事务集的⼀个并发调度的结果与某个串⾏调度等价,则称此并发调度是 可串⾏化调度。
-
若一个调度是冲突可串行化,则一定是可串行化的调度。即冲突可串行化调度是可串行化调度的充分条件,而非必要条件
- 冲突操作:指不同的事务对一个数据的读写操作和写写操作(涉及同一个数据库元素&至少有一个是写操作)
试述两段锁协议(2PL协议)的概念。
- 两段锁协议是指所有事务必须分两个阶段对数据项加锁和解锁。
- 在对任何数据进行读、写操作之前,首先要申请并获得对该数据的封锁;
- 在释放一个封锁之后,事务不再申请和获得任何其他封锁。
- “两段”的含义是,事务分为两个阶段:
- 第一阶段是获得封锁,也称为扩展阶段。在这阶段,事务可以申请获得任何数据项上的任何类型的锁,但是不能释放任何锁。
- 第二阶段是释放封锁,也称为收缩阶段。在这阶段,事务释放已经获得的锁,但是不能再申请任何锁。
(如果并发执行的所有事务遵循两段锁协议,那么对这些事务的任何调度都是可串行化调度)
(事务遵守两段锁协议是可串行化调度的充分条件,而非必要条件)
两段锁协议 和 防止死锁的一次封锁法 关系
一次封锁法要求每个事务必须一次将所有要使用的数据全部加锁,否则就不能继续执行。故一次封锁法遵守两段锁协议;但两段锁协议不要求事务必须一次将所有要使用的数据全部加锁,则遵守两段锁协议的事务可能发生死锁
什么是多粒度封锁?
- 封锁的粒度:封锁对象的大小
- 在一个系统中同时支持多种封锁粒度供不同的事务选择是比较理想的,这种方法称为多粒度封锁。
(封锁粒度与 系统的并发度&并发控制的开销密切相关)
封锁的对象有哪些?
物理单元:页(数据页或索引页)、物理记录等
逻辑单元:属性值、属性值的集合、元组、关系、索引项、整个索引、整个数据库
如何进行封锁的?
-
多粒度树:根节点是整个数据库,表示最大的数据粒度,叶节点表示最小的封锁粒度。
-
多粒度封锁协议:允许多粒度树中的每个结点被独立的加锁,对每一个结点加锁(显式封锁)意味着这个结点的所有后裔结点也被加以同样类型的锁(隐式封锁)
意向锁有哪些种类?
-
IS锁(意向共享锁):如果对一个数据对象加IS锁,表示它的后裔结点拟(意向)加S锁。(Intent Share Lock)
-
IX锁(意向排他锁):如果对一个数据对象加IX锁,表示它的后裔结点拟(意向)加X锁。(Intent Exclusive Lock)
-
SIX锁(共享意向排他锁):如果对一个数据对象加SIX锁,表示对它加S锁,再加IX锁,即SIX=S+IX。(Share Intent Exclusive Lock)
(可能加载不同后代节点上)
(沿对角线对称)
意向锁补充
-
锁的强度:指它对其他锁的排斥程度(上高下低)
-
一个事务在申请封锁时以强锁代替弱锁是安全的,反之不然
-
申请封锁:自上而下
释放封锁:自下而上
三、习题
1.选
2004
(D)
2.填
3.判
2004
(错 遵守两端所协议,则这些事务的任何并发调度一定可串行化,反之不行)
4.简答
5.计算
四、课后题
1.在数据库中为什么要并发控制?并发控制技术能保证事务的哪些特性?
- 数据库是共享资源,通常有许多个事务同时在运行。当多个事务并发地存取数据库时就会产生同时读取和/或修改同一数据的情况。若对并发操作不加控制就可能会存取和存储不正确的数据,破坏数据库的一致性。所以数据库管理系统必须提供并发控制机制。
- 并发控制可以保证事务的【一致性】和【隔离性】
2.并发操作可能会产生哪几类数据不一致?用什么方法能避免各种不一致的情况?
- 并发操作带来的数据不一致性包括三类
- 丢失修改(LostUpdate)
两个事务T1和T2读入同一数据并修改,T2提交的结果破坏了(覆盖了)T1提交的结果,导致T1的修改被丢失。
(发生在两个写事务间) - 不可重复读(Non-RepeatableRead)
不可重复读是指事务T1读取数据后,事务T2执行更新操作,使T1无法再现前一次读取结果。
不可重复读包括三种情况:- 事务T1读取某一数据后,事务T2对其做了修改,当事务T1再次读改数据时,得到与前一次不同的值
- 事务T1按一定条件从数据库中读取了某些数据记录后,事务T2删除了其中部分记录,当T1再次按相同条件读取数据时,发现某些记录消失了
- 事务T1按一条件从数据库中读取某些数据记录后,事务T2插入了一些记录,当T1再次按相同条件读取数据时,发现多了一些记录后两种不可重复读有时也称为幻影(phantom row)现象
(发生在读事务和更新事务间)
- 读“脏”数据(DirtyRead)
读“脏”数据是指事务T1修改某一数据,并将其写回磁盘,事务T2读取同一数据后,T1由于某种原因被撤销,这时T1已修改过的数据恢复原值,T2读到的数据就与数据库中的数据不一致,则T2读到的数据就为“脏”数据,即不正确的数据。
(发生在读和写事务间)
- 丢失修改(LostUpdate)
- 避免不一致性的方法和技术就是并发控制。并发控制的主要技术有封锁技术、时间戳方法、乐观控制方法、多版本并发控制方法等
3.什么是封锁?基本的封锁类型有几种?试述它们的含义。
- 封锁就是事务T在对某个数据对象例如表、记录等操作之前,先向系统发出请求,对其加锁。加锁后事务T就对该数据对象有了一定的控制,在事务T释放它的锁之前,其他的事务不能更新此数据对象。
- 基本的封锁类型有两种: 排它锁(简称X锁) 和共享锁(简称S锁)。
- 排它锁又称为写锁。若事务T对数据对象A加上X锁,则只允许T读取和修改A,其他任何事务都不能再对A加任何类型的锁,直到T释放A上的锁。这就保证了其他事务在T释放A上的锁之前不能再读取和修改A。
- 共享锁又称为读锁。若事务T对数据对象A加上S锁,则事务T可以读A但不能修改A,其他事务只能再对A加S锁,而不能加X锁,直到T释放A上的S锁。这就保证了其他事务可以读A,但在T释放A上的S锁之前不能对A做任何修改。
4.如何用封锁机制保证数据的一致性
DBMS在对数据进行读、写操作之前首先对该数据执行封锁操作,DBMS 按照一定的封锁协议,对并发操作进行控制,使得多个并发操作有序地执行,就可以避免丢失修改、不可重复读和读“脏”数据等数据不一致性。
5.什么是活锁?活锁的产生原因和解决方法
- 事务等待时间过长,似乎被锁住了,实际可能被激活
(比如:线程A和B都需要过桥(都需要使用进程),而都礼让不走(那到的系统优先级相同,都认为不是自己优先级高),就这么僵持下去.(很绅士,互相谦让)
) - 产生原因:当一系列封锁不能按照其先后顺序执行时,就可能导致一些事务无限期等待某个封锁,从而导致活锁
- 解决方法:先来先服务
6.什么是死锁?请给出预防死锁的若干方法。
- T1等待T2而T2等待T1,T1和T2两个事务永远不能结束,形成死锁
- 预防死锁通常有两种方法:
- 一次封锁法
要求每个事务必须一次将所有要使用的数据全部加锁,否则就不能继续执行。 - 顺序封锁法
预先对数据对象规定一个封锁顺序,所有事务都按这个顺序实行封锁。
- 一次封锁法
7.请给出检测死锁发生的一种方法,当发生死锁后如何解除死锁?
- 检测死锁发生:超时法或事务等待图法。
- 通常采用的方法是选择一个处理死锁代价最小的事务,将其撤消,释放此事务持有的所有锁,使其他事务得以继续运行下去。
(超时法:如果一个事务的等待时间超过了规定的时限,就认为发生了死锁。)
8.什么样的并发调度是正确的调度?
- 可串行化的调度是正确的调度。
- 多个事务的并发执行是正确的,当且仅当其结果与按某一次序串行地执行它们时的结果相同,我们称这种调度策略为可串行化的调度。
15.为什么要引进意向锁? 意向锁的含义是什么?
-
引进意向锁是为了提高封锁子系统的效率。
-
意向锁的含义是:对任一结点加锁时,必须先对它的上层结点加意向锁。引进意向锁后,系统对某一数据对象加锁时不必逐个检查与下一级结点的封锁冲突了。
16.试述常用的意向锁:IS锁,IX锁,SIX锁,给出这些锁的相容矩阵。
- IS锁:如果对一个数据对象加IS锁,表示它的后裔结点拟(意向)加S锁。例如,要对某个元组加S锁,则要首先对关系和数据库加IS锁
- IX锁:如果对一个数据对象加IX锁,表示它的后裔结点拟(意向)加X锁。例如,要对某个元组加X锁,则要首先对关系和数据库加IX锁。
- SIX锁:如果对一个数据对象加SIX锁,表示对它加S锁,再加IX锁,即SIX = S + IX。
相容矩阵