数据库管理系统中的死锁
当两个或更多进程需要完成其执行所持有的其他进程所拥有的某些资源时,就会发生死锁。
在上图中,进程1拥有资源1并需要资源2。同样,进程2拥有资源2并需要资源1。这些进程都需要其他进程的资源才能完成,但它们都不愿意放弃它们的资源。因此,进程1和进程2陷入了死锁状态。
阅读更多:MySQL 教程
科夫曼条件
仅当4个科夫曼条件成立时,才会发生死锁。这些条件不一定是互斥的。它们是:
互斥
应该有一个资源,一次只能由一个进程持有。在下面的图中,只有一个资源R1的实例,并且它只被进程P1持有。
持有和等待
一个进程可以持有多个资源,并仍然从正在持有这些资源的其他进程请求更多资源。在下面的图中,进程P1持有资源R1和R2,并请求进程P2持有的资源R3。
无抢占
不能通过强制手段从进程中抢占资源。进程只能自愿释放资源。在下面的图中,进程P1不能从进程P2中强制抢占资源R3。只有在P2执行完成后自愿放弃资源时,它才会被释放。
循环等待
一个进程正在等待由第二个进程持有的资源,第二个进程正在等待由第三个进程持有的资源,依此类推,直到最后一个进程正在等待由第一个进程持有的资源。这形成了一个循环链。例如:进程P1被分配了资源R1,并请求资源R2。类似地,进程P2被分配了资源R2,并请求资源R1。这形成了一个循环等待循环。
一个进程正在等待由第二个进程持有的资源,第二个进程正在等待由第三个进程持有的资源,依此类推,直到最后一个进程正在等待由第一个进程持有的资源。这形成了一个循环链。例如:进程P1被分配了资源R1,并请求资源R2。类似地,进程P2被分配了资源R2,并请求资源R1。这形成了一个循环等待循环。
死锁检测
资源调度程序可以检测到死锁,因为它跟踪分配给不同进程的所有资源。在检测到死锁后,可以使用以下方法解决死锁:
- 所有涉及死锁的进程都被终止。这并不是一个好的方法,因为进程所做的所有进展都被摧毁了。
- 资源可以从某些进程中抢占并给予其他进程,直到死锁被解决为止。
死锁预防
在发生死锁之前,严格检查每个事务以确保其不会导致死锁。如果存在任何可能导致死锁的事务,将不允许其执行。
有一些死锁预防方案使用时间戳,以确保不会发生死锁。这些方案包括:
- 等待 – 死锁方案
在等待 – 死锁方案中,如果事务T1请求持有事务T2的资源,则可能会出现以下两种情况之一:
- TS(T1) < TS(T2) – 如果T1比T2更老,即T1比T2更早进入系统,则T1允许等待该资源,该资源将在T2完成其执行时释放。
- TS(T1) > TS(T2) – 如果T1比T2更年轻,即T1在T2之后进入系统,则T1被杀死。稍后,它将以相同的时间戳重新启动。
- 伤口 – 等待方案
在伤口 – 等待方案中,如果事务T1请求持有事务T2的资源,则可能会出现以下两种情况之一:
- TS(T1) < TS(T2) – 如果T1比T2更老,即T1比T2更早进入系统,则允许回滚T2或伤害T2。然后T1获取资源并完成其执行。稍后使用相同的时间戳重新启动T2。
- TS(T1) > TS(T2) – 如果T1比T2更年轻,即T1在T2之后进入系统,则T1允许等待该资源,该资源将在T2完成其执行后释放。
避免死锁
最好避免死锁而不是死锁发生后再采取措施。等待图可用于避免死锁。但是,在大型数据库中,它会变得非常复杂,因此仅适用于较小的数据库。
等待图
等待图显示资源和事务之间的关系。如果事务请求资源或已经持有资源,则在等待图中显示为边缘。如果等待图包含一个循环,则系统中可能存在死锁,否则不会。
忽略死锁 – 鸵鸟算法
鸵鸟算法意味着死锁被简单地忽略,并且假定它永远不会发生。这是因为在某些系统中,处理死锁的成本比简单地忽略死锁高得多,因为它很少发生。因此,简单地假定死锁永远不会发生,如果出现死锁,则重新启动系统。