posts - 93,comments - 0,views - 12737

基于锁的协议

锁机制用于控制 并发访问 数据项

锁协议是事务在请求和释放锁时需要遵循的一组规则。锁协议的目的是确保事务的并发执行不会导致数据的不一致性,同时帮助系统避免死锁和其他问题

锁的两种模式

  • 排它锁(Exclusive Lock,X模式)

    • 目的:一个事务在对数据项进行操作时,可以对数据项进行 读和写 操作

    • 请求方式:使用 lock-X 指令来请求排它锁

    • 特点:只有获得排它锁的事务才能访问数据项,其他事务无论是读还是写都无法访问该数据项

  • 共享锁(Shared Lock,S模式)

    • 目的:一个事务可以 只读 数据项

    • 请求方式:使用 lock-S 指令来请求共享锁

    • 特点:多个事务可以同时对同一个数据项加共享锁,但所有这些事务只能读取数据项,不能修改

锁请求的流程

  • 加锁:事务向 并发控制管理器(Concurrency-Control Manager) 提出锁请求

  • 授权:事务在锁请求被批准后,才能继续执行,进行读写操作

  • 解锁:锁定的数据项在事务完成操作后,需要通过 Unlock 指令释放锁,使得其他事务可以访问该数据项

锁兼容矩阵

1

  • 共享锁是兼容的,多个事务可以同时持有共享锁

  • 排它锁是不兼容的,一旦有事务持有排它锁,其他任何事务都不能持有该数据项的任何锁(共享锁或排它锁)

  • 如果某个事务 请求的锁与现有的锁不兼容,它将等待,直到冲突的锁被释放,之后才能获得锁

陷阱 --- Pitfalls

2

以上这个调度会造成 死锁,就是这两个事务都无法在改变自身状态了,T3持有B的排他锁,T4持有A的共享锁,然后T3需要访问A才能继续运行,T4需要访问B才能继续运行,这就构成了一个循环,造成了死锁

  • 不正确的锁使用(比如不加锁或过早释放锁) 可能导致 数据不一致性,例如脏读或丢失更新等问题

  • 如果事务在 请求其他锁之前不释放当前锁,可能导致 死锁,事务相互等待,无法继续执行

  • 并发控制管理器设计不当,导致某些事务不断被其他事务排队或推迟处理,也就是一直被插队,无限期的等待资源,这会造成 饥饿

两阶段锁协议 --- Two-Phase Locking Protocol,2PL

  • 阶段1 --- 增长阶段(Growing Phase)

    可以获取锁,不能释放锁

  • 阶段1 --- 收缩阶段(Shrinking Phase)

    可以释放锁,不能获取锁

该协议确保所有的事务调度都是 冲突可串行化 的,通过对每个事务的 锁点 Lock Point(即获取最后一个锁的时刻) 进行排序,能够得到一个有效的串行化顺序,但不能确保避免 死锁

严格两阶段锁协议 --- Strict Two-Phase Locking Protocol

2PL在某些情况下可能导致 级联回滚(Cascading Rollback)

  • 级联回滚:当一个事务发生回滚(由于某些错误或冲突),它可能会导致其他依赖该事务的事务也回滚

  • 严格两阶段锁协议:在该协议中,事务 必须保持所有的独占锁直到它提交或回滚。换句话说,事务在释放任何锁之前,必须确保它已经完成了所有操作并且已经确定提交或者回滚

严谨两阶段锁协议 --- Rigorous Two-Phase Locking Protocol

比严格两阶段锁协议 更加严格,事务在整个执行过程中都必须持有 所有的锁,直到它提交或回滚,保证了事务可以 按照提交的顺序串行化

锁转换 --- Lock Conversions

锁转换在两阶段锁协议中的使用方式:

  • 第一阶段:

    • 事务可以 获取 一个 共享锁

    • 事务也可以 获取 一个 排它锁

    • 事务还可以将共享锁 升级 为排它锁

  • 第二阶段:

    • 事务可以 释放 已获取的 共享锁或排它锁

    • 事务还可以将排它锁 降级 为共享锁

基于图的协议

图形协议是一种替代两阶段锁协议(2PL) 的事务并发控制机制,它通过 定义数据项的访问顺序来控制事务的执行顺序

它不直接使用传统的锁(如共享锁或独占锁),而是使用 图结构 来确保事务之间的访问顺序符合一定规则,从而保证数据库操作的串行化

  • 部分排序(Partial Ordering):对于数据库中的每个数据项 会定义一个 部分排序。这意味着并不是所有的数据项之间都必须有明确的顺序关系,但某些数据项之间会有顺序要求。也就是定义访问B之前必须先访问A这样子

  • 数据库图(Database Graph):数据库的所有数据项和它们之间的顺序关系可以被表示为一个 有向无环图(Directed Acyclic Graph, DAG),我们称之为 数据库图(Database Graph)。在这个图中,节点代表数据项,而有向边表示数据项之间的访问顺序。通过这种图结构,事务在访问数据项时的顺序被明确规定

树协议

树协议是图形协议中的一种简单形式,它的工作原理是:事务按照某种层次结构(树形结构)来访问数据项,并且遵循树的遍历顺序

在树协议中,事务的访问顺序是从根节点开始,按照树的结构依次访问各个数据项。树形结构的特点是 没有环确保了冲突可串行化和避免了死锁

树协议只允许使用排它锁

4

如上述这张图,每个节点表示数据项,要访问某个节点,必须先获取到该节点的父节点的锁

图形协议中,事务可能必须访问他们不想访问的数据,增加了锁开销和等待时间

多粒度锁协议 --- Multiple Granularity

事务在锁定一个较大数据单位(如表)时,会隐式地锁定该单位下的所有较小数据单位(如行或列)

不同粒度的锁具有不同的并发性和开销:

  • 较低的粒度(如行级锁)具有更高的并发性但开销更大

  • 较高的粒度(如表级锁)则会有较低的开销,但并发性较差

7

意图锁 提供了在 树的较高层次上指示事务在较低层次进行锁定的意图,这有助于优化锁的管理并减少对所有后代节点的检查

  • IS:表示某个节点的较低层次正在加共享锁

  • IX:表示某个节点的较低层次正在加排它锁或共享锁

  • SIX:表示该节点是共享锁,同时其子节点会加排它锁

8

意向锁(IS和IX) 之间互不冲突,因为他们只是一种意向,表示在为低层级的资源加锁时要预先获取的表锁,IS与S不冲突,都是共享,IS与S和IX都不冲突,所以IS和SIX也不冲突,其他类似

死锁处理

预防

  • Wait-Die Scheme(非抢占式)

    • 原理:在这个机制下,事务根据其 时间戳的先后顺序 决定是否可以等待

      • 较老的事务可以等待较新的事务释放数据项

      • 较新的事务不能等待较老的事务,它们会被回滚(即放弃当前操作,重新开始)

    • 回滚次数:较新的事务可能会多次回滚,直到能够获取所需的数据项

    • 非抢占式:该机制 不允许中断或强行回滚 正在执行的事务。只有在事务自身不能获取锁时,它们才会回滚

  • Wound-Wait Scheme(抢占式)

    • 原理:与 Wait-Die Scheme 不同,Wound-Wait Scheme 是抢占式的

      • 较老的事务会 强行回滚(wound) 较新的事务,而不是等待它释放资源

      • 较新的事务可以等待较老的事务释放数据项

    • 回滚次数:相比于 Wait-Die Scheme,Wound-Wait Scheme 的回滚次数可能会更少,因为 较老的事务会主动中断较新的事务

    • 抢占式:该机制允许较老的事务 强行回滚 较新的事务,减少了等待,但可能导致较新的事务频繁被回滚

  • Timeout-Based Schemes(基于超时的方案)

    • 原理:在这种机制下,事务 等待锁的时间有一个最大限制,超过这个时间后,事务会被回滚

      • 如果事务等待锁的时间超过了指定的超时阈值,它就会被中止,系统将回滚该事务
    • 避免死锁:这种方案能够避免死锁,因为事务不会无休止地等待锁

    • 实现简单:这种方案相对容易实现,但存在一些问题:

      • 可能出现饿死:如果事务总是因为超时而被回滚,它可能无法获得锁,也可能导致资源分配的不公平

      • 难以确定合理的超时值:如何设定合适的超时值比较困难。如果超时太短,事务会频繁回滚;如果超时太长,又可能导致系统反应迟缓

检测

wait-for图
8

恢复

Rollback 回滚

posted on   Dylaris  阅读(26)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示