暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

事务管理——并发控制

于小江的百宝箱 2022-02-14
815

在这个“圣诞节”,或许你没有平安果,没有NPY,但你有《数据库原理与应用》可以复习啊!


上次谈了事务特性以及保证持久性的数据库恢复技术,这次谈保证隔离性的并发控制



重点一览

  • 破坏隔离性带来的数据不一致

  • 三级封锁协议及效果

  • 死锁的检测及解决

  • 可串行化调度的判断与两段锁协议

  • 多粒度封锁协议,意向锁及加锁顺序

  • 锁的相容矩阵及巧记

并发控制及其必要性

破坏隔离性带来的数据不一致

  • 丢失修改:T1修改数据后,数据又被T2修改成其他值。

  • 读脏数据:T1读取T2修改后的数据后,T2触发回滚,数据恢复未修改前的状态。

  • 不可重复读:T1读取数据后

  1. T2修改此数据,T1再次读取数据,但和第一次读取的数据已不一致。

  2. T2增加或删除数据,T1再次读取数据,读取数据不一致(幻影现象

并发控制

用正确的方式调度并发操作,使一个事务的执行不受其他事务的干扰,避免造成数据的不一致。


封锁和封锁协议

事务在对数据对象进行操作之前,先向操作系统申请对该对象加锁。加锁后其他事务在操作该对象时会受到限制。

根据受到的限制不同,最基础的锁分为两类:共享锁和排他锁。

共享锁(读锁,S):已加S锁的对象只能再加S锁。

排它锁(写锁,X):已加X锁的对象不能再加任何锁。

封锁协议

有了锁,我们就要考虑:

  • 加什么锁

  • 何时加锁,何时释放

规定这些内容的规则被称为封锁协议。常用的封锁协议是三级封锁协议。

三级封锁协议

一级封锁协议:事务在修改数据之前必须先对其加X锁,直到事务结束才释放。

二级封锁协议:一级封锁协议 + 事务在读取数据前必须先加S锁,读完后即可释放S锁

三级封锁协议:一级封锁协议 + 事务在读取数据之前必须先对其加S锁,直到事务结束才释放

三级封锁协议的异同及效果对比见下表:


活锁与死锁

封锁技术可以有效地解决并行操作的一致性问题,但也带来一些新的问题,导致事务长期等待无法运行

概念

活锁:某个事务请求封锁,但一直被其他事务插队,解决方法是先到先服务

死锁:两个以上的事务分别请求封锁对方已经封锁的数据

死锁的预防

  • 一次封锁法

    • 一次封锁所有要使用的数据,否则不继续执行

    • 缺点:降低并发度:难以事先确定要使用的数据

  • 顺序封锁法

    • 预先对数据对象规定封锁顺序,所有事务按顺序封锁

    • 维护成本高,难于实现

死锁的诊断与解除

  • 思路:允许发生死锁,由DBMS定期检测并解除

  • 检测方法:

    • 以运行中的事务为结点,等待关系为有向边,构建有向图(事务等待图

    • 并发控制子系统周期性检查回路,存在回路则认为发生死锁

    • 若一个事务的等待时间超出预设时限,就认为发生死锁

    • 实现简单

    • 可能发生误判;合理预设时限难度较大

    • 超时法:

    • 等待图法

  • 消除方法:回滚策略

  1. 事务开始时,赋予每个事务唯一的时标

  2. 当一个事务对其他事务封锁的数据请求时,新事务退回,等待重试

  3. 事务退回重试后,时标保持不变


并发调度的可串行化

可串行化的调度策略

多个事务的并发执行是正确的,当且仅当其结果与某一次序串行地执行它们时的结果相同。称这种调度为可串行化调度。

可串行性

一个给定的并发调度,当且仅当它是可串行化的,才认为是正确调度。

这是并发事务正确调度的准则。

可串行化调度判断

对一个并发调度,若在保证冲突操作次序不变的情况下,通过交换两个事务不冲突操作的次序,可获得一个串行调度。则称该并发调度为冲突可串行化调度。

两个事务不冲突的操作:

  • 不同事务对同一数据的读读操作

  • 不同事务对不同数据的任意操作

可串行化调度保障——两段锁协议

  • 读写前加锁(扩张阶段

  • 释放锁后不能再申请锁(收缩阶段

注意

  1. 可串行化调度的判断方法和两段锁协议内容都是充分而非必要条件,可能有 不符合以上规则但仍具有可串行性的调度。最终还是要看并发调度的结果是否与某一串行调度的结果相同。

  2. 两段锁不能预防死锁


多粒度封锁

封锁粒度

封锁粒度指封锁目标的大小。

封锁粒度大,则并行度低,效率低,但开销小;封锁粒度小,并行度和效率都高,但系统开销大。

多粒度封锁

DBMS同时支持多种封锁粒度,供不同事务选择。

不同封锁粒度以树的形式组织,称为多粒度树。根节点是整个数据库。

多粒度封锁协议允许多粒度树的每个节点被独立地加锁。对一个结点加锁,意味着其所有后裔结点加了同样的锁。

多粒度封锁的实现

  1. 封锁的两种方式

  • 显式封锁:直接在本结点加锁

  • 隐式封锁:本结点没有直接加锁,但在上层加了锁

  • 冲突检查:

    由于新出现隐式封锁,新加锁时需要考虑:

    这么多检查,尤其是第三个,下层结点何其多,烦死了好伐!

    所以出现了一种新型锁——意向锁,可以考虑检查冲突3。

    1. 是否与本结点已有显式封锁冲突

    2. 是否与本结点已有隐式封锁冲突

    3. 新加锁对下层结点的隐式封锁是否与其已有显式封锁冲突

  • 意向锁——免于逐个检查下层结点的显式封锁

    如果对一个结点加意向锁,说明正在对其下层结点加锁;要想对结点加锁,必须对其上层结点加意向锁。(充分必要)

    意向锁分类:

    • SIX锁:S+IX锁,表示将对整个表进行读取,同时对部分子结点做修改。

    • IX锁:将对下层结点加X锁

    • IS锁:将对下层结点加S锁

  • 处理顺序:在多粒度树上,从上而下申请从下而上释放(与两段锁协议神似)。

    1. 锁的相容矩阵

      内容

      一种速记

      1. 相容矩阵对称,记一半即可(废话)

      2. 先找X锁,X锁和所有锁冲突

      3. 再找IS锁,和X锁之外的的锁都相容

      4. 再找SIX锁,和除X和IS之外的锁都冲突

      5. IX,S锁自相容

      6. S与IX锁冲突

        (穷途末路,无奈之举,建议理解原理)


              微信不开放留言功能,若对文章内容有疑问或发现错误想要指正请进入公众号留言。


      点击“阅读原文”,访问我的个人博客“于小江的百宝箱”,浏览更多数据库笔记

      文章转载自于小江的百宝箱,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

      评论