DBMS 包含一个集中式锁管理器,用于决定事务是否可以获取锁。使用锁为可串行化的事务动态生成执行排期。
锁的类型#
共享锁,多个事务可以同时持有共享锁,从而可以在读取同一个对象。
排他锁,同一时间只能被一个事务持有。允许事务修改对象。持有此锁可防止其他事务在对象上获取其他锁(S/X)。
事务需要从锁管理器获取锁。锁管理器根据其他事务当前持有的锁来放行或阻止请求。当事务不再需要锁来访问对象时,它们必须释放锁。锁管理器更新其内部锁表,其中包含有关所有事务持有的锁正在等待锁的事务信息。DBMS 的锁表不需要持久化,因为当 DBMS 崩溃时任何事务都会自动中止。然而,仅靠锁是不够的。需要辅以并发控制协议,以确保正确使用锁。
2PL#
两阶段锁协议是一种悲观的并发控制协议。它使用锁来确定是否允许事务动态访问数据库中的对象。该协议不需要提前知道事务将执行的所有查询。
分为两个阶段。生长阶段和收缩阶段。在生长阶段只能获取锁,在收缩阶段只能释放锁。
就其本身而言,2PL 足以保证冲突的可串行化性。它生成的优先级图为有向无环图。但是它容易受到级联中止的影响。即当一个事务中止,然后必须回滚另一个事务时,这会导致资源浪费。
缺陷:
- 仍然可能有脏读
- 可能导致死锁
- 2PL 会阻止一些实际上是可串行化的排期(因此可能会限制并发性)
SS2PL#
如果在第一个事务提交之前,一个事务写入的任何值不会被另一个事务读取或覆盖,则排期是严格的。Strong Strict 2PL(也称为 Rigorous 2PL)是 2PL 的变体,它仅在事务的提交阶段释放锁。
此方法的优点是 DBMS 不会出现级联中止。DBMS 还可以通过还原已修改元组的原始值来撤消已中止事务的更改。但是,SS2PL 会生成更谨慎 / 悲观的计划,从而进一步限制并发性。
死锁检测#
为了检测死锁,DBMS 会创建一个等待图,其中事务是节点,如果事务 Ti 正在等待事务 Tj 释放锁,则存在从 Ti 到 Tj 的有向边。系统将定期检查等待图中的周期(通常带有后台线程),然后决定如何打破它。构造图形时不需要锁存器,因为如果 DBMS 在一次传递中错过了死锁,它将在随后的传递中找到它。请注意,在死锁检查的频率(使用 CPU 周期)和死锁被打破之前的等待时间之间存在权衡。当 DBMS 检测到死锁时,它将选择要中止的 “受害者” 事务以打破循环。受害事务将重新启动或中止,具体取决于应用程序调用它的方式。DBMS 在选择受害者以打破僵局时可以考虑多个事务属性:
按年龄(最新或最早的时间戳)。2. 按进度(执行的查询最少 / 最多)。3. 按已锁定的项目的 #。4. 通过需要回滚的事务的 #。5. 过去重启交易的次数 # 次(以避免饥饿)。
没有一个选择比其他选择更好。许多系统都使用这些因素的组合。选择要中止的受害者事务后,DBMS 还可以决定回滚事务更改的程度。它可以回滚整个事务,也可以回滚足够的查询来打破僵局。
死锁避免#
死锁预防 2PL 不是让交易尝试获取他们需要的任何锁,然后处理死锁,而是在交易发生之前阻止交易导致死锁。当一个事务试图获取由另一个事务持有的锁(这可能导致死锁)时,DBMS 可以杀死其中一个事务。为了实现这一点,为事务分配了优先级(可能基于时间戳,较旧的事务具有更高的优先级)。这些方案保证没有死锁,因为在等待锁时只允许一种类型的方向。当事务重新启动时,DBMS 将重用相同的时间戳。在死锁预防下,有两种方法可以杀死交易:・等待死亡(“老等待年轻”):如果请求交易的优先级高于持有交易,则等待。否则,它会中止(死亡)。・Wound-Wait(“Young Waits for Old”):如果请求交易的优先级高于持有交易,则持有交易将中止(受伤)并释放锁。否则,请求事务将等待。记住这些 - 如果协议是 X-Y,那么如果请求事务具有较高的优先级,它将是 X,如果请求事务的优先级较低,它将是 Y。
锁的粒度#
如果一个事务想要更新 10 亿个元组,它必须向 DBMS 的锁管理器请求 10 亿个锁。这将很慢,因为事务在获取 / 释放锁时必须闩锁锁管理器的内部锁表数据结构。或者,如果事务在只需要读取一个值时锁定整个表,则并行性的机会就会减少。为了处理这种权衡,DBMS 使用锁层次结构来同时处理不同粒度级别的锁。例如,它可以在表上获取一个具有 10 亿个元组的锁,而不是 10 亿个单独的锁。当事务获取此层次结构中对象的锁时,它会隐式获取其所有子对象的锁,因此单写锁无法获取任何元组锁。但是,如果表上没有锁,则允许在不同的元组上使用多个元组级锁,从而实现并行性。
数据库锁层次结构: 1. 数据库级别(略少) 2. 表级别(非常常见) 3. 页面级别(通用) 4. 元组级别(非常常见) 5. 属性级别(稀有) 重要的是,如果事务使用元组级锁,则需要传达没有其他事务可以获取页面级锁(或更高级别的锁),因为这会发生冲突。为了便于实现这一点,意图锁是隐式锁,它表示在较低级别持有显式锁。・意向共享 (IS):表示使用共享锁在较低级别进行显式锁定。
・Intention-Exclusive (IX):表示使用独占锁或共享锁在较低级别显式锁定。・共享 + 意图独占 (SIX):根植于该节点的子树在共享模式下显式锁定,而显式锁定则使用独占模式锁在较低级别完成
https://www.youtube.com/watch?v=pS2_AJNIxzU
https://15445.courses.cs.cmu.edu/fall2023/slides/16-twophaselocking.pdf
15-445/645 Database Systems (Fall 2022) - Lecture Notes - 16 Two-Phase Locking (cmu.edu)