知识卡片

活锁与死锁的区别及应对策略

普通读书笔记卡

内容

锁机制引入了两类新问题,它们的表现和成因完全不同,混为一谈会导致 应对措施用错方向。活锁是”事务一直在动,但永远轮不到自己”:事务T2 请求某个数据上的锁被拒绝后进入等待,但系统在锁释放时反复优先批准 后来的事务T3、T4等的请求,T2可能被无限期地插队、永远得不到锁—— 系统整体在正常运转(不断有事务在获得锁、执行、释放锁),只是T2这 一个事务被持续”饿死”。解决活锁的思路很直接:改成”先来先服务”的 公平调度策略,锁释放后优先批准等待队列里最早提出申请的事务,从 根源上消除”后来者持续插队”的可能。死锁是”多个事务互相卡死,谁都 动不了”:T1锁住了A、正在等待B(被T2锁住),T2锁住了B、正在等待A (被T1锁住)——两个事务都在等对方释放自己需要的锁,形成循环等待, 双方都无法继续执行到提交。死锁不能靠”公平调度”解决,因为问题不是 谁先谁后的顺序问题,而是资源请求本身构成了一个闭环;应对思路分两类: 预防型是在设计阶段就用某种规则(如统一的加锁顺序)从结构上排除 循环等待的可能性,事中型是允许死锁发生,但系统定期检测是否存在 死锁(如构建等待关系图检查是否有环),一旦发现就主动挑一个事务 回滚、打破循环。活锁的本质是调度不公平,死锁的本质是资源请求形成 闭环,两者的诊断方法和解决方案完全不能互换。

参考来源

- 位置:《数据库原理(微课版)》第11章《事务处理技术》11.3.2节"锁的 粒度"(源文件:_epub-src/index_split_007.html) - 结论依据:原文明确"T1释放R上的锁后,系统有可能首先批准了T3的 加锁请求,T2继续等待……以此类推,T2有可能一直处于等待状态无法 获得锁。这就是活锁……避免活锁的一个简单方法是采用'先来先服务' 的策略""T1封锁了数据对象A,事务T2封锁了数据对象B。之后T1又申请 封锁B,因T2已封锁了B,于是T1等待T2释放B上的锁。接着T2又申请锁 数据对象A,因T1已封锁了A,T2也只能等待T1释放A上的锁……形成 死锁……主要有两类策略。一类策略是采取一定措施来预防死锁的出现; 另一类是允许出现死锁,采用一定手段定期诊断",因此可以推出两类 问题的成因差异及各自的应对策略。 - 原始内容:避免活锁的一个简单方法是采用"先来先服务"的策略……解决 死锁问题的方法……主要有两类策略。一类策略是采取一定措施来预防 死锁的出现;另一类是允许出现死锁,采用一定手段定期诊断系统中有 无死锁,若有则解除之。