简单描述:
事务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.难以实现:很难事先确定每一个事务要封锁哪些对象
1.超时法 2.事务等待法(如果事务等待图存在回路,则表示系统中出现了死锁)
解除死锁:处理死锁代价最小的事务,将其撤销释放,将其它事务继续运行
多个事务的并发执行是正确的,当且仅当其结果与按某一次序串行地执行这些事务时的结果相同
DBMS对并发事务不同的调度可能会产生不同的结果
例:现在有两个事务,分别包含下列操作
事务T1:读B;A=B+1;写回A
事务T2:读A;B=A+1;写回B
现给出对这两个事务不同的调度策略
(a)
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、B的初值均为2。
按T1→T2次序执行结果为A=3,B=4
串行调度策略,正确的调度
(b)
T1 |
T2 |
|
Slock A |
|
X=R(A)=2 |
|
Unlock A |
|
Xlock B |
|
B=X+1=3 |
|
W(B) |
|
Unlock B |
Slock B |
|
Y=R(B)=3 |
|
Unlock B |
|
Xlock A |
|
A=Y+1=4 |
|
W(A) |
|
Unlock A |
|
假设A、B的初值均为2。
T2→T1次序执行结果为B=3,A=4
串行调度策略,正确的调度
T1 |
T2 |
Slock B |
|
Y=R(B)=2 |
|
|
Slock A |
|
X=R(A)=2 |
Unlock B |
|
|
Unlock A |
Xlock A |
|
A=Y+1=3 |
|
W(A) |
|
|
Xlock B |
|
B=X+1=3 |
|
W(B) |
Unlock A |
|
|
Unlock B |
执行结果与(a)、(b)的结果都不同
是错误的调度
T1 |
T2 |
Slock B |
|
Y=R(B)=2 |
|
Unlock B |
|
Xlock A |
|
|
Slock A |
A=Y+1=3 |
等待 |
W(A) |
等待 |
Unlock A |
等待 |
|
X=R(A)=3 |
|
Unlock A |
|
Xlock B |
|
B=X+1=4 |
|
W(B) |
|
Unlock B |
执行结果与串行调度(a)的执行结果相同
是正确的调度
https://blog.csdn.net/lee18254290736/article/details/79531550 参考大佬的博客
冲突操作是指不同的事务对同一个数据的读写操作和写写操作,其他操作是不冲突操作
不同事务的冲突操作和同一事务的两个操作不能交换(Swap)
今有调度Sc1=r1(A)w1(A)r2(A)w2(A)r1(B)w1(B)r2(B)w2(B)
把w2(A)与r1(B)w1(B)交换,得到:
r1(A)w1(A)r2(A)r1(B)w1(B)w2(A)r2(B)w2(B)
再把r2(A)与r1(B)w1(B)交换:
Sc2=r1(A)w1(A)r1(B)w1(B)r2(A)w2(A)r2(B)w2(B)
Sc2等价于一个串行调度T1,T2,Sc1冲突可串行化的调度
冲突可串行化调度是可串行化调度的充分条件
有3个事务
T1=W1(Y)W1(X),T2=W2(Y)W2(X),T3=W3(X)
调度L1=W1(Y)W1(X)W2(Y)W2(X) W3(X)是一个串行调度。
调度L2=W1(Y)W2(Y)W2(X)W1(X)W3(X)不满足冲突可串行化。
但是调度L2是可串行化的,因为L2执行的结果与调度L1相同,Y的值都等于T2的值,X的值都等于T3的值
1.是并发事务正确调度的准则
2.一个给定的并发调度,当且仅当它是可串行化的,才认为是正确调度
事务含义:
事务遵守两段锁协议是可串行化调度的充分条件,而不是必要条件。(可冲突化串行调度也只是充分条件)
含义:封锁对象(逻辑单元,物理单元)的大小
逻辑单元:属性值,属性值集,元组,关系,索引项,整个索引,整个数据库。。。。
物理单元:页(数据页,索引页),物理记录。。。。
封锁粒度与系统的并发度和并发控制的开销密切相关:
1.封锁的粒度越大,数据库所能够封锁的数据单元就越少,并发度就越小,系统开销也越小;
2 .封锁的粒度越小,并发度较高,但系统开销也就越大(根节点是整个数据库,表示最大的数据粒度。叶节点是最小的)
选择封锁粒度:
------同时考虑封锁开销和并发度两个因素,适当选择封锁粒度
1.需要处理多个关系的大量元组的用户事务:以数据库为封锁单位
2.需要处理大量元组的用户事务:以关系为封锁单元
3.只处理少量元组的用户事务:以元组为封锁单位
隐式封锁(上级结点加锁) 和 显式封锁(数据对象本身直接加锁) 是多粒度封锁中一个数据对象的方式,效果相同
对任一结点加基本锁,必须先对它的上层结点加意向锁
常用意向锁:
1.意向共享锁(IS)如果对一个数据对象加IS锁,表示它的后裔结点拟(意向)加S锁。
2.意向排他锁(IX)如果对一个数据对象加IX锁,表示它的后裔结点拟(意向)加X锁。
3.共享意向排他锁(SIX)如果对一个数据对象加SIX锁,表示对它加S锁,再加IX锁,即SIX = S + IX。
例: 对某个表加SIX锁,则表示该事务要读整个表(所以要对该表加S锁),同时会更新个别元组(所以要对该表加IX锁)
申请封锁时应该按自上而下的次序进行
释放封锁时则应该按自下而上的次序进行
具有意向锁的多粒度封锁方法优点:
提高了系统的并发度
减少了加锁和解锁的开销
在实际的数据库管理系统产品中得到广泛应用
v数据库的并发控制以事务为单位
v数据库的并发控制通常使用封锁机制
v活锁: 先来先服务
v 死锁:
预防方法
Ø一次封锁法
Ø顺序封锁法
死锁的诊断与解除
Ø超时法
Ø等待图法