在分布式环境下,由于通讯延迟的不确定性、地域的分布性以及资源和数据的高度共享性等影响因素的存在,使得死锁预防和检测变得极为困难。在分布式计算系统中,有两个以上的进程在并发执行,每个进程都在等待被其它的进程所占用的系统资源而不能继续运行,即导致系统中任何一个进程都无法运行下去(死循环),这就产生了死锁。
当且仅当以下四个条件同时成立时,死锁才会发生:
互斥。同一个资源在同一时刻最多只能被一个进程占用。
占有并等待。必然有一个进程至少占用了系统中的一个资源,同时在等待获取被其他进程占用的资源。
不可剥夺。一个进程不能剥夺被其他进程占用的资源。
循环等待。在等待图中有一个循环。
在图中,事务T1
在站点A
对数据x
持有一个锁,又要对站点B
的数据y
请求封锁,而事务T2
在站点B
对数据y
持有一个锁,又要对站点A
的数据x
请求封锁。这样就形成了相互等待,两个事务谁也不能继续执行。由于这两个事务不在同一站点,引起全局死锁。
A
站点T1
拿着x
锁想要y
锁,B
站点T2
拿着y
锁想要x
锁,相互等待引起全局死锁.
分布式数据库中的数据冗余也会增加更新数据时引起死锁的机会。因为更新时需要对全部副本加拒绝锁,含有副本的每个站点上都有可能等待另一个事务释放锁,但每一个事务只有在它全部完成后才能释放,因此造成全局死锁.
站点A:存储x和y的副本, 发出事务T1:read(x),write(y)
站点B:存储y和z的副本, 发出事务T2:read(y),write(z)
站点C:存储z的副本, 发出事务T3:read(z),write(x)
写操作必须要锁来保证
A站点:拿着x锁想要y锁
B站点:拿着y锁想要z锁
A站点:拿着z锁想要x锁
什么是锁?有哪两种锁?
答:
锁是最常用的并发控制机构,是防止其他事务访问指定资源,实现并发控制的一种手段。
排他锁(X写锁
):当数据被加上写锁,其他事务不能对该数据进行读和写;
共享锁(S读锁
):当数据被加上读锁,允许其他事务对该数据进行读,不允许写。
等待图分类
局部等待图(LWFG)
全局等待图(GWFG)
T1等待T2释放对y的共享锁(s)
T2等待T3释放对z的共享锁(s)
T3等待T1释放对x的共享锁(s)
换而言之
一到6.3 假设四个事务 T1、T2、T3、T4
之间的等待关系如下;
T1->T2->T3->T4
如果T1与T2运行于站点1,T3与T4运行于站点2,则这两个站点的局部等待图如图所示。注意:仅通过检查这两个局部等待图来找出死锁是不全面的,因为这个死锁是全局的。然而,通过检查全局等待图可以轻松地找出死锁,为区别它们,可把全局等待图中站点之间的等待用点线表示,如图所示。
有三种处理死锁的策略:
预防死锁
。限制请求,保证前文提到的四个死锁条件中至少有一个不能发生, 从而预防死锁;
避免死锁
。如果结果状态是安全的, 就将资源动态地分给进程。如果至少有一个执行序列使所有的进程都能完成运行, 那么这个状态就是安全的;
检测死锁和从死锁中恢复, 允许死锁发生, 然后发现并解除死锁。
死锁预防和避免采用一种悲观方法,即认为死锁会经常发生并试图阻止或避免它。虽然死锁避免策略在集中式系统中广为应用,并且有许多算法,但是在分布式系统中很少使用。
这是因为在分布式系统中没有全局时钟,检查安全性状态会涉及到大量进程和资源的计算,从而引起昂贵的开销。死锁检测和恢复使用乐观方法,然而这种方法对于死锁发生频繁的应用程序可能并不有效。
Wait-Die
):总是重启较年轻的事务(非占先权)Wound-Wait
) :年轻的等待年老的, 较年轻的重启,而重启事务并不一定是目前正申请的事务 (占先权)(Ti,才允许Ti等待
(Ti>Tj)
,则Ti被终止并带有同一时间戳重新启动非占先权:
年老的事务允许等待年轻的事务,如果年轻事务需要年老事务的锁,则直接终止重启.某种意义上事务变老就失去了优先权.
由于年老事务持锁时间,年轻事务可能会被重启多次.
占先权:
年老的事务需要年轻事务的锁时,年轻事务就必须无条件服从终止重启,将自己的锁释放,成就年老的事务.某种意义上事务变老就增加了优先权.
由于年轻事务遇到年老事务就会主动让位,释放所有的锁重启,所以只会被重启一次.
LWFG
传送给死锁检测器, 死锁检测器构造GWFG
, 并在其中寻找回路GWFG
, 并在其中寻找回路DBMS
中的死锁检测器基于资源访问类型,各个站点被划分到不同的群组中,并将这些群组以层次方式组织.每个群组中.一个指定的群组负责用集中式算法检测本群组内的死锁.
层次式死锁检测的步骤
层次式死锁检测方法示意图
分布式死锁的检测更加困难,因为每个站点只有整个系统的一个部分视角,因此,当检测涉及一个以上站点的死锁时,就需要站点之间的协作。在分布式死锁检测算法中,所有的站点共同协作来检测和处理死锁。不像集中式死锁检测算法,分布式死锁检测算法不受单个站点故障的影响,并月没有站点会被死锁检测活动淹没
LWFG
),是为了确定全局死锁EX
是指的本地事务正在等待的其他事务所在的还不确定的站点分布式死锁检测算法需要对每个站点的锁管理器进行统一悠改。这种统一性使得它们更易于实现。然而,这种算法存在大量的信息传输例如,在例图中, 站点1向站点2发送潜在的死锁信息,而站点2也向站点1发送它的潜在死锁信息。这种情况下,两个站点上的死锁检测器都将检测到死锁。除了会导致不必要的信息传输外,还会有一个问题,即每个站点有可能会选择不同的牺牲者事务进行撤销。
为了解决这个问题,使用如下规则:令某个站点上的LWFG
中可能引起分布式死锁的路径为Ti->...->Tj
,仅当ts(Ti)< ts(Tj)
时,局部死锁检测器向前传输回路信息(正向传输)。这种方法将传输量减少了一半,则在例图中,站点1有一条传输路径T1->T2->T3
,而站点2的传输路径为T3->T4->T1
.这样,假定每个事务的下标表示其时标,则仅有站点1会向站点2发送信息。