文档介绍:数据库系统概论14
适用于教师试讲、学校演讲、教学课件、说课大赛
不可重复读的三种情况
事务T1读取某一数据后,事务T2对其做了修改,当事务T1再次读该数据时,得到与前一次不同的值
事务T1按一定条件从数据库中读取了某些数据记录(C恢复为100)
等待
Unlock C
等待
④
获得Slock C
R(C)=100
⑤
Commit C
Unlock C
例
事务T1在对C进行修改之前,先对C加X锁,修改其值后写回磁盘
T2请求在C上加S锁,因T1已在C上加了X锁,T2只能等待
T1因某种原因被撤销,C恢复为原值100
T1释放C上的X锁后T2获得C上的S锁,读C=100。避免了T2读“脏”数据
不读“脏”数据
活锁和死锁
封锁技术可以有效地解决并行操作的一致性问题,但也带来一些新的问题
死锁
活锁
活锁
活 锁
解决活锁
采用先来先服务的策略
当多个事务请求封锁同一数据对象时
按请求封锁的先后次序对这些事务排队
该数据对象上的锁一旦释放,首先批准申请队列中第一个事务获得锁
死锁
T1
T2
lock R1
•
•
Lock R2
•
•
Lock R2.
•
等待
•
等待
Lock R1
等待
等待
等待
等待
•
死 锁
解决死锁的方法
两类方法
1. 预防死锁
2. 死锁的诊断与解除
避免死锁的方法---死锁的预防
产生死锁的原因是两个或多个事务都已封锁了一些数据对象,然后又都请求对已为其他事务封锁的数据对象加锁,从而出现死等待。
预防死锁的发生就是要破坏产生死锁的条件
常用方法
一次封锁法
顺序封锁法
一次封锁法
要求每个事务必须一次将所有要使用的数据全部加锁,否则就不能继续执行
存在的问题
降低系统并发度
难于事先精确确定封锁对象
顺序封锁法
顺序封锁法是预先对数据对象规定一个封锁顺序,所有事务都按这个顺序实行封锁。
顺序封锁法存在的问题
维护成本
数据库系统中封锁的数据对象极多,并且在不断地变化。
难以实现:很难事先确定每一个事务要封锁哪些对象
死锁的预防(续)
结论
在操作系统中广为采用的预防死锁的策略并不很适合数据库的特点
DBMS在解决死锁的问题上更普遍采用的是诊断并解除死锁的方法
避免死锁的方法---死锁的诊断与解除
死锁的诊断
超时法
事务等待图法
超时法
如果一个事务的等待时间超过了规定的时限,就认为发生了死锁
优点:实现简单
缺点
有可能误判死锁
时限若设置得太长,死锁发生后不能及时发现
等待图法
用事务等待图动态反映所有事务的等待情况
事务等待图是一个有向图G=(T,U)
T为结点的集合,每个结点表示正运行的事务
U为边的集合,每条边表示事务等待的情况
若T1等待T2,则T1,T2之间划一条有向边,从T1指向T2
事务等待图
等待图法(续)
并发控制子系统周期性地(比如每隔数秒)生成事务等待图,检测事务。如果发现图中存在回路,则表示系统中出现了死锁。
死锁的诊断与解除(续)
解除死锁
选择一个处理死锁代价最小的事务,将其撤消
释放此事务持有的所有的锁,使其它事务能继续运行下去
并发调度的可串行性
DBMS对并发事务不同的调度可能会产生不同的结果
什么样的调度是正确的?
可串行化调度
可串行化(Serializable)调度
多个事务的并发执行是正确的,当且仅当其结果与按某一次序串行地执行这些事务时的结果相同
可串行性(Serializability)
是并发事务正确调度的准则
一个给定的并发调度,当且仅当它是可串行化的,才认为是正确调度
可串行化调度(续)
[例]现在有两个事务,分别包含下列操作:
事务T1:读B;A=B+1;写回A
事务T2:读A;B=A+1;写回B
现给出对这两个事务不同的调度策略
串行化调度,正确的调度
T1
T2
Slock B
Y=R(B)=2
Unlock B
Xlock A
A=Y+1=3
W(A)
Unlock A
Slock A
X=R(A)=3
Unlock A
Xlock B
B=X+1=4
W(B)
Unlock B
串行调度(a)
假设A、B的初值均为2。
按T1→T2次序执行结果为A=3,B=4
串行调度策略,正确的调度
串行化调度,正确的调度
T1
T2
Slock A
X=R(A)=2
Unlock A
Xlock B
B=X+1=3
W(B)
Unlock B