23/5/5 数据库系统 1
在多用户数据库系统中,当多个用户并发存取数据库时就会产生多个事务同时存取同一数据的情形。若不加控制,可能会存取和存储不正确的数据,造成数据库的不一致性。 在并发操作情况下,对事务的操作序列的调度是随机的,考虑飞机订票系统,若按下面的序列调度:
23/5/5 数据库系统 2
考虑飞机订票系统中的一个活动序列: 甲售票点读出某航班的机票余额 A ,设 A=16 , 乙售票点读出同一航班的机票余额 A ,也为 16 , 甲售票点卖出一张机票,修改余额 AA—1 , A 变为 15 ,把 A 写回数据库 乙售票点也卖出一张机票,修改余额 AA—1 , A 也为 15 ,把 A 写回数据库。
卖出两张机票,而余额只减少 1 。错误! 这种情况就造成数据库的不一致性,这种不一致性是由并发操作引起的。
并发操作带来的数据不一致性包括三类:
23/5/5 数据库系统 3
一、并发操作可能造成的不一致性 1 、丢失修改: 两事务读出同一数据并修改,先写回的数据修改丢失时间 事务 T1 事务 T2 A
16 读出 A= 读出 A=
AA—1 写回 A=
AA—1 写回 A=
15A
T1 的修改丢失
16
15
15
16 15A
我的数据呢?
23/5/5 数据库系统 4
2 、不可重复读 事务 T1 读取某一数据,事务 T2 读取并修改了同一数据; 事务 T1 为了对读取值进行校对再读此数据,得到了不同的结果。时间 事务 T1 事务 T2
读出 A=50 , B=100 求和 =150
读出 B=100 计算 B B2 ,写回 B
读出 A=50 , B= 求和 =
200250
T1 读出 B 的值与原来的不符,验算结果不对
23/5/5 数据库系统 5
有三种情况可造成不可重复读( 1 )事务 T1 读取某一数据后,事务 T2 对其做了修改,事务 T1 再次读取该数据时,发现与前次不同;( 2 )事务 T1 按一定条件读取了某些数据记录后,事务 T2 删除了其中的部分记录,事务 T1 再次按相同条件读取记录时,发现有些记录不存在;( 3 )事务 T1 按一定条件读取了某些数据记录后,事务 T2 插入了一些记录,事务 T1 再次按相同条件读取记录时,发现多了一些记录。
23/5/5 数据库系统 6
3 、读出“脏”数据 事务 T1 修改某一数据,事务 T2 读取同一数据; 事务 T1 由于某种原因被撤消,则 T2 读到的就是“脏”数据。时间 事务 T1 事务 T2
读出 C=100 计算 CC2 ,写回 C
ROLLBACK C 恢复为 100 “ 脏”数据 读出 C=200
T2 读出的数据无效
C=200
23/5/5 数据库系统 7
产生上述三类不一致性的主要原因就是并发操作破坏了事务的隔离性。并发控制就是要用正确的方式调度并发操作,使某个事务的执行不受其它事务的干扰。
并发控制的技术是封锁,即事务在修改某个对象前,先锁住该对象,不允许其它事务读取或修改该对象,修改完毕或事务完成后再将锁打开。
23/5/5 数据库系统 8
§2 封锁( Locking )封锁的类型:排它锁( Exclusive Lock ,简称 X 锁,又称互斥锁): 若事务 T 对数据对象 R 加上 X 锁,则只允许 T 读、写 R , 禁止其它事务对 R 加任何锁,相应地其它事务就无法 读、写对象 R 。共享锁( Shared Lock ,简称 S 锁):
若事务 T 对数据对象 R 加上 S 锁,则 T 可以读 R ,但不可 以写 R ,且其它事务可以对 R 加 S 锁、但禁止加 X 锁。这 保证了事务 T 在释放 R 的 S 锁之前,其它事务只可以读 R , 不可以修改 R 。
23/5/5 数据库系统 9
§3 封锁协议1 、封锁协议( Locking Protocol ) 在运用 X 锁和 S 锁对数据对象加锁时,对何时申请 X 锁或 S 锁、持锁时间、何时释放等的一些约定。2 、三级封锁协议 基本方法: 事务在读数据对象 R 时先上 S 锁,封锁后才能读 R ,否则需等待; 事务在写数据对象 R 时先上 X 锁,封锁后才能写 R ,否则需等待; 何时释放锁( Unlock )?
23/5/5 数据库系统 10
根据上锁的类型和释放锁的时机,分为三种情况。1 级封锁协议 : 事务 T 在修改数据对象 R 之前必须先对其加X 锁,直到事务结束才释放。 2 级封锁协议 : 1 级封锁协议 + 事务 T 在读取数据对象 R 之前必须先对其加 S 锁,读完即释放 S 锁。3 级封锁协议 : 1 级封锁协议 + 事务 T 在读取数据对象 R 之前必须先对其加 S 锁, S 锁也是直到事务结束才释放。
23/5/5 数据库系统 11
1 级封锁协议 : 事务 T 在修改数据对象 R 之前必须先对其加X 锁,直到事务结束才释放。
分析: 时间 事务 T1 事务 T2 请求 X 锁 对 A 加 X 锁 读出 A=16 请求 X 锁 等待 AA—1
写回 A=15 Commit 释放 X 锁
对 A 加 X 锁 读出 A=15 AA—1 写回 A=14 Commit 释放 X 锁
……
作用: 防止丢失修改 保证事务是可恢复的 没有丢失修改
23/5/5 数据库系统 12
1 级封锁协议 : 事务 T 在修改数据对象 R 之前必须先对其加 X 锁,直到事务结束才释放。
分析(续):
时间 事务 T1 事务 T2 请求 X 锁 对 C 加 X 锁 读出 C=100 计算 CC2 写回 C
ROLLBACK ( C 恢复为 100 ) 释放 X 锁
仍然读出“ 脏”数据
读出 C=200C=200
T1 已对 C 加 X锁,为什么 T2 仍能读取 C ?因为 T2 在读取 C前未对 C 申请任何锁。
23/5/5 数据库系统 13
分析(续):
读出 A=50 , B=100 求和 =150
请求 X 锁 对 B 加 X 锁 读出 B=100 计算 B B2 ,写回 B Commit 释放 X 锁
读出 A=50 , B= 求和 =
时间 事务 T1 事务 T2
200250
仍然是不可重复读
1 级封锁协议 : 事务 T 在修改数据对象 R 之前必须先对其加 X 锁,直到事务结束才释放。
原因: T1 在读取 A 、 B 时未申请任何锁。
23/5/5 数据库系统 14
2 级封锁协议 : 1 级封锁协议 + 事务 T 在读取数据对象 R 之前必须先对其加 S 锁,读完即释放 S 锁。
分析:
作用: 防止丢失修改
时间 事务 T1 事务 T2 请求 X 锁 对 C 加 X 锁 读出 C=100 计算 CC2, 写回 C
ROLLBACK ( C 恢复为 100 ) 释放 X 锁
请求 S 锁 等待 防止读“脏”数据
对 C 加 S 锁 读出 C=100 释放 S 锁
…… 保证事务是可恢复的
23/5/5 数据库系统 15
对 A 加 S 锁对 B 加 S 锁释放 A 、 B 上的 S 锁
分析(续): 读出 A=50 , B=100 求和 =150
请求 X 锁 对 B 加 X 锁 读出 B=100 计算 B B2 ,写回 B Commit 释放 X 锁
读出 A=50 , B= 求和 =
时间 事务 T1 事务 T2
200250
仍然是不可重复读
对 A 加 S 锁对 B 加 S 锁释放 A 、 B 上的 S 锁
2 级封锁协议 : 1 级封锁协议 + 事务 T 在读取数据对象 R 之前必须先对其加 S 锁,读完即释放 S 锁。
23/5/5 数据库系统 16
3 级封锁协议 : 1 级封锁协议 +事务 T 在读取数据对象 R 之前必须先对其加 S 锁, S 锁也是直到事务结束才释放。
分析:
作用: 防止丢失修改
对 A 加 S 锁 对 B 加 S 锁 读出 A=50 , B=100 求和 =150 对 B 请求 X 锁 等待
读出 A=50 , B=100 求和 =150 Commit 释放 A 、 B 上的 S 锁
时间 事务 T1 事务 T2
对 B 加 X 锁 读出 B=100 计算 B B2 ,写回 B Commit 释放 X 锁
防止读“脏”数据 保证可重复读
……
… 保证事务是可恢复的
23/5/5 数据库系统 17
三级封锁协议的主要区别在于什么操作需要申请封锁,以及何时释放封锁。
23/5/5 数据库系统 18
对 R1 上 X 锁 对 R2 上 X 锁 对 R2 请求 X 锁 等待 对 R1 请求 X 锁 等待
§4 活锁和死锁 使用封锁机制,得不到锁的事务就要等待,这可能出现下述局面:
T1 T2
…
……
T1 和 T2 将永远等待下去
23/5/5 数据库系统 19
1 、活锁( Livelock ): 数据对象不断处于上锁、开锁的交替状态,某个事务有可能为该对象上锁,但始终没有得到上锁机会而永久等待下去的情形。例如:
T1 T2 T3 T4 …….封锁 R 请求封锁 R 请求封锁 R等待 请求封锁 R 等待释放锁
封锁 R
等待
释放锁 封锁 R……
……
…………
… 如此下去, T2 可能永远不能封锁 R。
23/5/5 数据库系统 20
避免活锁: 如采用先来先服务策略。
2 、死锁( Deadlock ): 多个事务因封锁冲突(竞争资源)而永远等待下去的情形。如: 对 R1 上 X 锁 对 R2 上 X 锁 对 R2 请求 X 锁 等待 对 R1 请求 X 锁 等待
T1 T2
…
…… T1 和 T2 将永远等待下去
23/5/5 数据库系统 21
死锁问题的解决方法预防死锁诊断死锁并解除
一次封锁法顺序封锁法超时法等待图法
( 1 )一次封锁法 每个事务必须将所要求的数据对象全部上锁后才能执行读写操作,否则释放占用的资源。存在的问题 使数据的上锁时间增长,降低了系统的并发性。 很难确定事务执行期间需封锁的数据对象。有些一开始不需要封锁的对象,随着数据库数据的变化,可能变成封锁对象,为避免此种情况发生,只能扩大封锁范围。
23/5/5 数据库系统 22
( 2 )顺序封锁法 对所有数据对象规定一个封锁顺序,所有事务均按这个顺序实行封锁。存在的问题: 很难维护数据对象的封锁顺序,因为数据对象很多并在不断地增加、减少。 很难确定事务需封锁那些对象,从而很难按规定的顺序封锁。 上述两种方法虽然都可以有效地预防死锁,但都存在一些问题,因此真正实施起来并不方便。所以预防死锁的策略不很适合数据库的特点, DBMS普遍采用诊断死锁并解除的方法。
23/5/5 数据库系统 23
( 3 )超时法 当一个事务的等待时间超过了规定的时限,就认为发生了死锁。存在的问题: 时限规定的太短,可能误判死锁,规定的太长,又不能及时发现死锁。因此很难确定一个合理的时限。( 4 )等待图法 用一个有向图表示事务等待的情况。图中节点表示事务,边表示事务间的等待关系。并发控制子系统定时检查此图,若发现有回路,则产生死锁。发生死锁时,解除死锁的方法: 选择一个处理代价最小的事务,将其撤消。
ROLLBACK
23/5/5 数据库系统 24
§5 并发调度的可串行性 多事务并发执行,对并发操作的调度是随机的,如何保证正确性?1 、调度( Schedule ): 若干个事务的操作构成的序列。2 、串行与并发 对调度 S 中的两个事务 Ti 和 Tj ,若 S 中 Ti 的操作都在 Tj 的操作之前(或反之),则称 Ti 、 Tj 是串行执行的;否则称作是并发执行的。 若调度 S 中的所有事务都是串行执行的,则称 S是串行的( Serial )。
23/5/5 数据库系统 25
3 、可串行化( Serializable ) 多个事务的并发执行是正确的,当且仅当其结果与按某一次序串行地执行它们时的结果相同,称这种调度为可串行化的调度。
调度 可串行化的不可串行化的
串行的并发的并发的
所有事务串行起来的调度策略一定是正确的调度策略。尽管一组事务可能有多个串行调度序列,且产生的执行结果不一定相同,但每个序列都不会将数据库置于不一致状态。
23/5/5 数据库系统 26
4 、一点说明: 对若干个事务,不同的并发调度策略其最终的执行结果不一定完全相同。但只要它们的调度是可串行化的,则都是正确调度。如:事务 T1 :读 B ; AB+1 ;写回 A 。 事务 T2 :读 A ; BA+1 ;写回 B 。
T1 T2 读 BAB+1写 A 读 A BA+1 写 B
T1 T2 读 A BA+1 写 B读 BAB+1写 A
T1 T2 读 B 读 AAB+1写 A BA+1 写 B
结果 A=3B=4
假设 T1 、 T2 执行前 A=2 , B=2
A=4B=3
A=3B=3
23/5/5 数据库系统 27
T1 T2 读 B 读 AAB+1写 A BA+1 写 B
T1 T2
读 B
读A
AB+1写 A
BA+1 写 B
分析右边的调度: 若采用 2 级封锁协议,则可能得到这样的调度
仍是不可串行化的调度若采用 3 级封锁协议,则可能得到这样的调度永久等待,造成死锁
Slock B
Unlock B Slock A
Unlock AXlock A
Unlock A Xlock B
Unlock B
Slock B读 B Slock A 读 AXlock AAB+1 Xlock B写 AUnlock AUnlock B BA+1 写 B Unlock A Unlock B因此,三级封锁协议不能保
证得到可串行化的调度,也会造成死锁。
23/5/5 数据库系统 28
§6 两段锁协议1 、两段封锁协议(也称两相上锁协议) ( 2-Phase-Locking Protocol ,简写 2PL ) ( 1 )在对任何数据进行读、写操作之前,事务首先要申请并获得对该数据的封锁(读时 S 锁,写时 X 锁) ( 2 )在释放一个封锁之后,事务不再申请和获得新的封锁。例:Lock A Lock B Lock C Unlock B Unlock A Unlock CLock A Lock B Unlock B Lock C Unlock A Unlock C
23/5/5 数据库系统 29
含义:事务封锁分两个阶段 第一阶段是扩展阶段( Growing Phase ),只进行上锁 第二阶段是收缩阶段( Shrinking Phase ) , 只进行解锁
2 、 2PL 的正确性 定理:若所有事务都遵守两段封锁协议,则对这些事务的任何并发调度策略都是可串行化的。3 、说明 2PL 是并发控制正确性的充分条件充分条件,但不是必要条件。即若所有事务都遵守 2PL ,则这些事务的任何并发调度都是可串行化的,反之,一个并发调度是可串行化的,不一定所有事务都遵守 2PL 。
23/5/5 数据库系统 30
Lock A Lock B Lock C Unlock B Unlock A Unlock C允许读写
不允许读写此时才允许读写
预防死锁的一次封锁法
2PL
2PL 会产生死锁。 2PL 不隐含预防死锁的一次封锁法,但一次封锁法肯定遵守 2PL 。
23/5/5 数据库系统 31
习题: P145页第 5题设有 3 个事务: T1 、 T2 和 T3 ,其所包含的动作为: T1 : A=A+2 T2 : A=A*2 T3 : A=A-1
设 A 的初值为 3 ,若这 3 个事务并行执行,则可能的调度策略有几种? A 的最终结果分别是什么?给出一个可串行化的调度,使用封锁协议。