学无先后,达者为师

网站首页 编程语言 正文

剖析数据库中重要而又常被曲解的概念

作者:暗诺星刻 更新时间: 2022-05-11 编程语言

剖析数据库中重要而又常被曲解的概念

  • 排他锁
  • 共享锁
  • 意向锁
    • 粒度树
    • 意向锁
  • 两段锁协议
  • 一级封锁协议
  • 二级封锁协议
  • 三级封锁协议
  • 脏读
  • 不可重复读
  • 幻影行
  • 可串行化

排他锁

  • 排他锁(exclusive locks):指的满足此条件的锁:当某事务对某数据加上排他锁之后,直到该事务释放这个锁之前,其它事务不能再对这个数据再加排他锁和共享锁。

共享锁

  • 共享锁(share locks):指的满足此条件的锁:当某事务对某数据加上共享锁之后,直到所有事务都释放了对该数据加上的共享锁之前,任何事务都不能对该数据加上排他锁,但可以对其加共享锁。

【注意】

  排他锁、共享锁本身是无法直接限制事务对数据的读取和修改的。之所以看起来它们能够控制对数据的读取和修改,这需要依赖每个事务在读取和修改数据之前必须要遵守某种约定,这就是:如果要求在某些条件下,某事务需要加某种锁才能对数据进行操作,那么,所有其它事务在遇到同样情况下,也强制必须先加锁才能对数据进行操作,如果加锁加失败,则该事务需要等待。而锁之间是有排斥法则的,所以可以通过这个法则来间接实现对数据读取和修改上的限制。

  排他锁对应的要求条件往往是在对数据的修改之前,共享锁对应的则是读取。也就是说,如果对事务启用排他锁,往往意味着,任何事务在修改数据之前都要先加排他锁。如果对事务启用共享锁,往往意味着任何事务在读取数据之前都要先加共享锁。不过,可以自行规定加锁时机。


意向锁

  介绍这个概念之前,需要知道什么是粒度树。

粒度树

  • 粒度树:不同资源在概念上的包含关系称为粒度。不同资源之间的概念粒度会有不同,如行的粒度与表的粒度就有不同。一个资源可以分为粒度更小的资源。按照资源之间的包含关系所建立的树状结构称为粒度树。

意向锁

  • 意向锁:对粒度树中的某一个结点加意向锁时,代表这个结点下至少有一个子孙结点将要被加上 排他锁共享锁


    【提示】

      意向锁是为了减少对多粒度资源加 排他锁共享锁 时的开销。


两段锁协议

  • 两段锁(Two Phase Locking,简称 2PL)协议:当一个事务需要对很多资源加锁时,如果对这些资源的加锁顺序可分为如下两个阶段,则称其符合两段锁协议:

    • 拓展阶段:只进行加锁,不进行释放锁。

    • 收缩阶段:只释放锁,不进行加锁。

    如果该事务对这些资源进行适当分组,使得对每一组的加锁顺序都符合两段锁协议,则称该事务对整个资源的加锁顺序也符合两段锁协议。


    【提示】

      事务调度遵守两段锁协议时,一定满足可串行化,但遵守两段锁协议不是满足可串行化的充要条件。


一级封锁协议

  • 一级封锁协议:规定:任何事务在修改数据之前,必须先对其加本事务结束才会释放的排他锁,然后在加锁成功之后才能修改数据。

    一级封锁协议不能防止脏读、不可重复读。

二级封锁协议

  • 二级封锁协议:规定:任何事务除了要遵守级封锁协议之外,还应该遵守:在读取数据之前,

    • 如果自己已经对该数据加上了排他锁或共享锁,则直接读取数据,不再额外加锁。

    • 如果自己此时没有对该数据加上排他锁或共享锁,则必须先对其加共享锁,然后在加锁成功之后才能读取数据,不过在读取完数据之后就释放共享锁。

    二级封锁协议不能防止不可重复读。

三级封锁协议

  • 三级封锁协议:规定:任何事务除了要遵守级封锁协议之外,还应该遵守:在读取数据之前,

    • 如果自己已经对该数据加上了排他锁或共享锁,则直接读取数据,不再额外加锁。

    • 如果自己此时没有对该数据加上排他锁或共享锁,则必须先对其加本事务结束才会释放的共享锁,然后在加锁成功之后才能读取数据。

    三级封锁协议可以防止脏读、不可重复读,但不能防止旧读。

脏读

  • 脏读(dirty read):如果一个事务在读取数据之前,读到的是某事务在修改后、但提交之前的数据,这称为脏读。


    【注意】

      如果某事务读取到的数据是历史时期的某个一致性状态下的数据,这不能称之为 脏读,这应该叫做读。脏读 读出来的数据是一个处于中间状态下的数据,这种数据是没有意义的。而 旧读 读出来的数据是一种曾经的正确数据,使用这种数据有可能会导致问题,有可能不会。


不可重复读

  • 不可重复读(nonrepeatable read):在上一次查询之后,如果本事务没有主动变更数据,当本事务再次以相同的条件查询数据时,得到的数据与上一次不一致。(变更指更新、插入、删除,但不包括查找)

幻影行

  • 幻影行(phantom row):对于不同的数据库,可以是以下定义之一。

    • 在上一次查询之后,如果本事务没有主动变更数据,当本事务再次以相同的条件查询数据时,与上一次相比,数据的个数发生了变化。(变更指更新、插入、删除,但不包括查找)

      在这个定义中,幻影行属于不可重复读的范畴。

    • 满足以下条件之一即视为出现了幻影行:

      • 某事务连续以相同的条件查询数据时,查询的结果不全相同。(连续指的是查询操作中没有夹杂其它操作)

      • 本次变更数据时,涉及变更前的查询中不存在的数据,但此操作没有引发异常,而是成功变更了该数据。随后本事务再次以相同的条件查询数据时,与上一次查询相比,数据的个数发生了变化。(变更指更新、插入、删除,但不包括查找)

      在这个定义中,幻影行一定属于不可重复读。


【注意】

  不可重复读、幻影行描述的都是同一事务的操作。

  • 如果一个事务已经结束,然后又开启新的事务,此时这两个事务分别的查询结果不能用于证明事务是否满足不可重复读、幻影行。

    很多情况都会导致事务结束,如事务的提交、回滚、执行 DDL 语句、客户端断开等等。

  • 同一事务要求当前正在观测的事务不能结束,否则该事务结束之后的操作就不能隶属于同一事务。但这仅限于这正在被观测的事务,其它事务是可以任意开启、随时结束,这不影响对同一事务的要求。


可串行化

  • 可串行化(Serializable):如果一种调度事务执行的策略,使得每次多个事务并发执行时,其执行结果如果属于下面这个执行结果集中的任何一个结果,就认为这种调度策略满足可串行化。

    • 任意排列这些事务的执行次序。

    • 令这些事务依次执行,且上一次事务执行完,下一个事务才能执行。

原文链接:https://blog.csdn.net/wangpaiblog/article/details/122780648

栏目分类
最近更新