CMU15-445-Spring-2023-Project #4 - 前置知识(lec15-20)

Lecture #15_ Concurrency Control Theory

Motivation

并发控制:如何避免同时更新记录时出现race?
耐久性问题(恢复):断电时如何确保状态正确?

Transactions

事务是指在共享数据库上执行一个或多个操作序列(如 SQL 查询),以执行某些高级功能。它们是 DBMS 中变化的基本单位。事务必须是原子性的。
处理事务的简单方法是使用单个 Worker 一次执行一个事务。为了执行事务,DBMS 会复制整个数据库文件,并在新文件中进行事务更改。如果事务成功,新文件就会成为当前数据库文件。如果事务失败,DBMS 就会丢弃新文件,事务中的任何更改都不会被保存。这种方法速度很慢,因为它不允许并发事务,而且每次事务都需要复制整个数据库文件。
更好的方法是允许独立事务并发执行。
事务的范围仅限于数据库内部。它不能对外部世界进行更改,因为它不能回滚这些更改。

Definitions

从形式上看,数据库可以表示为一组固定的命名数据对象(A、B、C、…)。这些对象可以是属性、元组、页、表,甚至是数据库。
事务是对这些对象的一系列读写操作(即 R(A)、W(B))。
事务的边界由客户端定义。在 SQL 中,事务以 BEGIN 命令开始。事务的结果是 COMMIT 或 ABORT。对于 COMMIT,要么将事务的所有修改保存到数据库中,要么由 DBMS 改写并终止事务。对于 ABORT,事务的所有更改都会被撤销,就像事务从未发生过一样。 终止可能是自己造成的,也可能是 DBMS 造成的。
用于确保数据库正确性的标准由 ACID 构成。原子性(atomicity,或称不可分割性)、一致性(consistency)、隔离性(isolation,又称独立性)、持久性(durability)。

ACID: Atomicity

DBMS 保证事务是原子性的。事务要么执行所有操作,要么不执行任何操作。
Logging:记录 DBMS 记录所有操作,以便在事务中止时撤销操作。DBMS 在内存和磁盘中都保存有撤销记录。
Shadow Paging:DBMS 为事务修改的页面制作副本,事务对这些副本进行修改。只有当事务提交时,页面才会可见。这种方法在运行时通常比基于日志的 DBMS 慢。不过,这样做的一个好处是,如果只有单线程,就不需要日志记录,因此当事务修改数据库时,写入磁盘的次数就会减少。这也使恢复变得简单,因为只需删除未提交事务的所有页面即可。

ACID: Consistency

一致性意味着数据库在逻辑上是正确的。应用程序对数据提出的所有问题(即查询)都会返回逻辑上正确的结果。一致性有两个概念:数据库一致性和事务一致性。

ACID: Isolation

DBMS 为事务提供了一种错觉,即它们是单独在系统中运行的,这相当于一个以串行顺序执行事务的系统。但为了获得更好的性能,DBMS 必须交错执行并发事务的操作,同时保持隔离的假象。

  • Concurrency Control
    • DBMS 在运行时如何决定多个事务操作的适当交错;
    • 悲观:DBMS 假定事务会发生冲突,因此首先不会让问题出现;
    • 乐观:DBMS 假定事务之间的冲突很少发生,因此会选择在事务提交后处理冲突;
    • DBMS 执行操作的顺序称为执行时间表。我们希望在确保输出 "正确 "的同时,交错执行事务以最大限度地提高并发性。并发控制协议的目标是生成一个等同于某种串行执行的执行计划;
    • 如果两个操作是针对不同事务的,而且是在同一个对象上执行的,并且至少有一个操作是写入操作,那么这两个操作之间就会发生冲突;

可序列化有两种类型:冲突和视图。

  • Conflict Serializability
    • 如果两个计划涉及相同事务的相同操作,并且每一对冲突操作在两个计划中的排序方式相同,那么这两个计划表就是冲突等价的;
    • 我们可以通过交换不冲突的操作来验证计划是否可冲突序列化,直到形成序列计划。对于有很多事务的计划表来说,这种方法成本太高。验证计划表的更好方法是使用依赖关系图(优先级图,类似拓扑)。
  • View Serializability
    • 视图可序列化是一种较弱的可序列化概念,它允许所有可冲突序列化的计划表和 “盲写”(即在不先读取值的情况下执行写操作)。

CMU15-445-Spring-2023-Project #4 - 前置知识(lec15-20)_第1张图片
在这里插入图片描述

ACID: Durability

已提交事务的所有更改在崩溃或重启后必须是持久的。DBMS 可以使用日志记录或shadow paging来确保所有更改都是持久的。这通常需要将已提交事务存储在非易失性内存中。

Lecture #16_ Two-Phase Locking.md

Transaction Locks

需要一种方法来即时保证正确性。数据库管理系统使用锁为事务动态生成可序列化的执行计划。DBMS 包含一个集中式锁管理器,由它决定事务是否可以获取锁。
重要的是,lock不同于 B+ 树中使用的latch。latch保护DBMS内部数据结构不受并发线程的影响,而lock则保护数据库中的值不受并发事务的影响。例如,在 B+ 树中,只需在扫描中对单个叶子节点加latch,但如果一个事务尝试扫描叶子,而另一个事务尝试写入两个任意值,那么叶子扫描就需要lock整个表,而不仅仅是当前叶子。

  • Shared Lock (S-LOCK):共享锁允许多个事务同时读取同一个对象。如果一个事务持有共享锁,那么另一个事务也可以获得相同的共享锁。
  • Exclusive Lock (X-LOCK):独占锁允许一个事务修改一个对象。该锁可防止其他事务对该对象加锁(S-LOCK 或 X-LOCK)。同一时间只能有一个事务持有独占锁。

Two-Phase Locking

两阶段锁定(2PL)是一种悲观的并发控制协议,它使用锁来决定是否允许事务临时访问数据库中的对象。该协议无需提前知道事务将执行的所有查询。
第 1 阶段——Growing:在增长阶段,每个事务都会向 DBMS 的锁管理器申请所需的锁,锁管理器会批准/拒绝这些锁请求;
第 2 阶段——Shrinking:事务释放第一个锁后立即进入收缩阶段。在收缩阶段,事务只允许释放锁,不允许获取新锁。
2PL 本身就足以保证冲突的可序列性。它生成的时间表的优先级图是非回环的。但它容易受到级联中止的影响,即一个事务中止后,另一个事务必须回滚,从而造成浪费。
2PL 仍会出现脏读,也可能导致死锁。
如果一个事务写入的任何值在第一个事务提交之前永远不会被另一个事务读取或覆盖,那么这个计划就是严格的。strong strict 2PL 是 2PL 的一种变体,其中事务只在提交时释放锁。
这种方法的优点是 DBMS 不会发生级联中止。DBMS 还可以通过恢复已修改元组的原始值来回溯已中止事务的更改。不过限制了并发性。
image.png

Deadlock Handling

死锁是一个事务等待彼此释放锁的循环。在 2PL 中,有两种处理死锁的方法:检测和预防。

  • 死锁检测
    • 为了检测死锁,DBMS会创建一个等待图,其中事务是节点,如果事务 Ti 正在等待事务 Tj 释放锁,则存在一条从 Ti 到 Tj 的有向边。系统会定期检查等待图中的循环;
    • 当 DBMS 检测到死锁时,它会选择一个 “受害者” 事务中止,以打破循环。受害者事务是重新启动还是中止,取决于应用程序如何调用它。选择考虑多个事务属性(时间戳、最少/最多查询);
    • 在选择要中止的受害事务后,DBMS 还可以决定在多大程度上回滚事务的更改。它既可以回滚整个事务,也可以只回滚足够的查询来打破死锁;
  • 死锁预防
    • 当一个事务试图获取另一个事务持有的锁(这可能会导致死锁)时,DBMS会杀死其中一个事务。为了实现这一点,会给事务分配优先级(可能基于时间戳,时间越长的事务优先级越高);
    • Wait-Die:如果请求事务的优先级高于当前事务,它就等待。否则,它将中止(死亡);
    • Wound-Wait:如果请求事务的优先级高于持有事务,则持有事务中止并释放锁。否则,请求事务等待;

Lock Granularities

如果一个事务要更新 10 亿个数据元组,就必须向 DBMS 的锁管理器申请 10 亿个锁,速度会很慢,因为事务在获取/释放锁时,必须在锁管理器的内部锁表数据结构中获取锁。
相反,如果一个事务只需要读取一个值,却锁定了整个表,那么并行性的机会就会减少。为了处理这种权衡,DBMS 使用锁层次结构来同时处理不同粒度级别的锁。
当一个事务为该层次结构中的一个对象获取锁时,它隐式地获取了其所有子对象的锁,因此单写锁无法获取任何元组锁。但是,如果表上没有锁,则允许在不同的元组上使用多个元组级锁,从而实现并行性。
重要的是,如果一个事务使用元组级锁,它就需要告知其他事务不能抓取页面级锁(或更高级别的锁),因为这会产生冲突。

  • Intention-Shared (IS):表示在较低层次使用共享锁进行显式锁定;
  • Intention-Exclusive (IX):表示在较低层次使用独占或共享锁进行显式锁定;
  • Shared+Intention-Exclusive(SIX):允许多个事务同时读取数据,但当有事务有意向修改(独占锁)时,其他事务必须等待,以确保数据的一致性;

CMU15-445-Spring-2023-Project #4 - 前置知识(lec15-20)_第2张图片

Lecture #17_ Timestamp Ordering Concurrency Control.

Timestamp Ordering Concurrency Control

Timestamp Ordering(T/O)是乐观的并发控制协议,数据库管理系统假定事务冲突很少发生。DBMS 不要求事务在获准读/写数据库对象前获得锁,而是使用时间戳来确定事务的序列化顺序。
DBMS 可以使用系统时钟作为时间戳,但在夏令时等边缘情况下会出现问题。另一种方法是使用逻辑计数器,但这种方法存在溢出问题,以及在多台机器的分布式系统中维护计数器的问题。此外,还有结合使用的混合方法。

Basic Timestamp Ordering (BASIC T/O)

基本时间戳排序协议(BASIC T/O)允许在不使用锁的情况下读写数据库对象。取而代之的是,每个数据库对象 X 都会被标记上一次对该对象成功执行读取(记为 R-TS(X))或写入(记为 W-TS(X))的事务的时间戳。DBMS 会为每次操作检查这些时间戳。如果一个事务试图以违反时间戳排序的方式访问一个对象,该事务将被中止并重新启动。基本假设是,违反时间戳顺序的情况很少发生,因此重新启动的情况也很少发生。
对于读操作,TS需要和W-TS(X)比较,然后更新为TS和R-TS(X)的最大值。
对于写操作,TS需要和R-TS(X)、W-TS(X)比较。
对写操作的一种优化是,如果 TS < W-TS(X),DBMS 可以忽略写操作,允许事务继续,而不是中止并重新启动。这就是 Thomas Write Rule
问题:每次读取对象都需要写入时间戳;将数据复制到事务工作区和更新时间戳的开销很高;长期运行的事务可能会处于饥饿状态;在高并发系统中会受到时间戳分配瓶颈的影响;允许不可恢复的计划。

Optimistic Concurrency Control (OCC)

乐观并发控制(OCC)是另一种乐观并发控制协议,它也使用时间戳来验证事务。当冲突数量较少时,OCC 效果最佳。这是当所有事务都是只读的,或者事务访问的是不相关的数据子集。
在 OCC 中,DBMS 为每个事务创建一个私有工作区。事务的所有修改都会应用到该工作区。读取的任何对象都会复制到工作区,写入的任何对象都会复制到工作区并在那里修改。任何事务都无法读取其他事务在其私有工作区中所做的修改。
OCC 包括三个阶段:

  1. 读取阶段:在此,DBMS 跟踪事务的read/write set,并将其写入内容存储在私有工作区中。
  2. 验证阶段:当事务提交时,检查它是否与其他事务冲突(RW或WW)。这通过时间戳排序完成。
  3. 写入阶段:如果验证成功,将私有工作区的更改应用到数据库。否则,将中止并重新启动事务。

问题:将本地数据复制到事务私有工作区的开销很大;验证/写入阶段的瓶颈;与其他协议相比,终止可能会造成更多浪费,因为只有在事务已经执行之后才会发生。

Isolation Levels

序列化允许忽略并发问题,但强制执行序列化可能会导致并行性过低,从而限制性能。
隔离级别控制一个事务受其他并发事务影响的程度。
异常:

  • 脏读:读取未提交的数据。
  • 不可重复读:重做读取会检索到不同的结果。
  • 幻读:插入或删除会导致相同范围扫描查询的不同结果

Isolation Levels (Strongest to Weakest)

  • SERIALIZABLE: 无幻读,所有读取均可重复,并且无脏读
    • Possible implementation: Index locks + Strict 2PL
  • REPEATABLE READS:可能会有幻读
    • Possible implementation: Strict 2PL
  • READ-COMMITTED:可能会发生幻读和不可重复读
    • Possible implementation: Strict 2PL for exclusive locks, immediate release of shared locks after a read
  • READ-UNCOMMITTED:所有异常情况都可能发生
    • Possible implementation: Strict 2PL for exclusive locks, no shared locks for reads

两种其他isolation level:

  • CURSOR STABILITY:在REPEATABLE READS和READ-COMMITTED之间 ,防止丢失更新的异常情况,IBM DB2默认的isolation level。
  • SNAPSHOT ISOLATION:确保事务中进行的所有读取都会看到事务启动时存在的数据库的一致快照,仅当事务的写入不与自该快照以来进行的任何并发更新发生冲突时,事务才会提交。

CMU15-445-Spring-2023-Project #4 - 前置知识(lec15-20)_第3张图片

Lecture #18_ Multi-Version Concurrency Control

Multi-Version Concurrency Control

多版本并发控制(MVCC)是一个比并发控制协议更大的概念。它涉及 DBMS 设计和实施的方方面面。MVCC 是 DBMS 中使用最广泛的方案。
使用 MVCC 时,DBMS 会在数据库中维护单个逻辑对象的多个物理版本。 当事务写入对象时会创建该对象的新版本。事务读取对象时,会读取事务开始时存在的最新版本。
MVCC 的基本概念/优点是写入器不会阻塞写入器,读取器不会阻塞读取器。这意味着,当其他事务读取旧版本时,一个事务可以修改对象。
使用 MVCC 的一个优势是,只读事务可以读取数据库的一致快照,而无需使用任何类型的锁。此外可以轻松支持time-travel query,即在其他时间点的状态查询。
基于 MVCC 的典型数据库设计包括:
1.有一个版本控制存储区,存储同一逻辑对象的不同版本。

  1. 当事务开始时,数据库管理系统会(通过复制事务状态表)对数据库进行快照。
  2. DBMS 使用快照来确定哪些版本的对象对事务可见
    MVCC 有四个重要的组成: 1.并发控制协议 2.版本存储 3.垃圾回收 4.索引管理
    快照隔离是指在事务启动时为事务提供一致的数据库快照。快照中的数据值只包括已提交事务中的值,事务在完成之前与其他事务完全隔离。写入内容保存在事务的私有工作区中,或与事务元数据一起写入存储中,只有在事务成功提交后才会被数据库看到。

Version Storage

DBMS 使用元组的指针字段为每个逻辑元组创建一个版本链,该版本链实质上是一个按时间戳排序的版本链表。这样,DBMS 就能在运行时找到特定事务可见的版本。
方法 1:Append-Only Storage
逻辑元组的所有物理版本都存储在同一个表空间中。每次更新只需将元组的新版本追加到表中并更新版本链。版本链可以从最旧到最新排序,这需要在查找时遍历版本链;也可以从最新到最旧排序,这需要为每个新版本更新索引指针。
方法 2:Time-Travel Storage
DBMS 维护一个单独的time-travel table,用于存储元组的旧版本。 每次更新时,DBMS 都会将元组的旧版本复制到time-travel table中,并用新数据覆盖主表中的tuple。主表中tuple的指针指向time-travel table中的过去版本。
**方法 #3:Delta Storage

**DBMS 只在所谓的delta存储段中存储delta或tuple之间的变化,而不是整个过去的tuple。然后,事务可以通过迭代 deltas 来重新创建旧版本。这导致写入速度比时间旅行存储更快,但读取速度较慢。

Garbage Collection

DBMS 需要从数据库中删除可回收的物理版本。如果没有活动事务可以 "看到 "该版本,或者该版本是由一个已中止的事务创建的,那么该版本就是可回收的。
方法 #1:Tuple-level GC
DBMS 直接检查元组,从而找到旧版本。有两种方法可以实现这一目的:

  • Background Vacuuming:独立线程定期扫描表,查找可回收版本。一个简单的优化方法是维护一个 “脏页面bitmap”,它可以跟踪哪些页面在上次扫描后被修改过。这样,线程就可以跳过没有更改的页面。
  • Cooperative Cleaning:工作线程在遍历版本链时识别可回收版本。如果数据未被访问,则永远不会被清理。

**方法 2:Transaction-level GC

**每个事务负责跟踪自己的旧版本,这样 DBMS 就不必扫描tuple。每个事务都维护自己的读/写集,当事务完成时,垃圾回收器就能利用它来确定要回收哪些tuple。DBMS 会确定已完成事务创建的所有版本何时不再可见。

Index Management

所有主键索引总是指向版本链头。DBMS 更新主键索引的频率取决于系统是否会在更新元组时创建新版本。
二级索引的管理更为复杂。有两种处理方法
方法 1:逻辑指针
DBMS 为每个元组使用一个固定的标识符,该标识符不会改变。这就需要一个额外的间接层,将逻辑标识符映射到元组的物理位置。然后,元组的更新只需更新间接层中的映射即可。
方法 2:物理指针
DBMS 使用版本链头的物理地址。这就需要在版本链头更新时更新每个索引。

Lecture #19_ Logging Schemes

Crash Recovery

恢复算法是确保数据库一致性、事务原子性和故障后耐用性的技术。当数据库崩溃时,内存中所有尚未提交到磁盘的数据都有可能丢失。恢复算法的作用是防止崩溃后信息丢失。
每个恢复算法都包括两个部分:

  • 正常事务处理期间的操作,以确保 DBMS 能够从故障中恢复。
  • 故障后的操作,以将数据库恢复到确保原子性、一致性和持久性的状态。

恢复算法中使用的关键原语是 UNDO 和 REDO。

  • UNDO:消除未完成或已中止事务的影响的过程。
  • REDO:重新应用已提交事务的影响以保证持久性的过程。

Storage Types

易失:DRAM、SRAM
非易失:HDD、SDD
稳定存储:不存在,只能近似

Failure Classification

由于 DBMS 根据底层存储设备分为不同的组件,因此 DBMS 需要处理多种不同类型的故障。其中一些故障可以恢复,而另一些则无法恢复。

  • Transaction Failures
    • 当事务出错而必须中止时,就会发生事务失败。逻辑错误(完整性、违反约束)和内部状态错误(死锁)是导致事务失败的两类错误。
  • System Failures
    • 系统故障是指托管 DBMS 的底层软件或硬件出现意外故障。崩溃恢复协议必须考虑到这些故障。
    • 软件故障:DBMS 执行出现问题(如未捕获的除以零异常),系统不得不停止运行。
    • 硬件故障:DBMS 所在计算机崩溃(如电源插头被拔掉)。我们假设非易失性存储内容不会因系统崩溃而损坏。这被称为 "故障停止 "假设,可简化流程恢复。
  • Storage Media Failure
    • 存储介质故障是物理存储设备损坏时发生的不可修复故障。 当存储介质发生故障时,必须从存档版本恢复 DBMS。DBMS 无法从存储故障中恢复,需要人工干预。
    • 不可修复的硬件故障:磁头崩溃或类似的磁盘故障会破坏全部或部分非易失性存储。假定破坏是可检测的。

Buffer Pool Management Policies

一旦 DBMS 告知它已提交事务,任何事务的更改都是持久的。
如果事务中止,则部分更改不会持久。
**窃取策略(STEAL)**决定了事务能否将属于不同事务的未提交更改写入磁盘(覆写已提交)。
**强制策略(FORCE)**决定了 DBMS 是否要求在允许事务提交(即向客户机返回提交消息)之前,在非易失性存储中进行事务的所有更新。
强制写入更容易恢复,因为所有更改都会被保留,但运行时性能较差。
最容易实施的缓冲池管理策略叫做 “NO-STEAL + FORCE”。在这种策略中,DBMS 永远不必撤消已中止事务的更改,因为这些更改没有写入磁盘;也永远不必重做已提交事务的更改,因为在提交时,所有更改都会被保证写入磁盘。
CMU15-445-Spring-2023-Project #4 - 前置知识(lec15-20)_第4张图片
该方法有个限制就是所有数据必须适用内存。

Shadow Paging

DBMS 在写入时复制页面,维护两个不同版本的数据库:
master:仅包含已提交事务中的更改。
shadow:临时数据库,包含未提交事务的更改。
更新只在影子副本中进行。当事务提交时,影子副本会原子切换成为新的master。旧的master最终会被垃圾回收。这就是 NO-STEAL + FORCE 系统的一个例子。
数据库根指向主页表,而主页表又指向磁盘上的页面(所有这些页面都包含已提交数据)。更新事务发生时,会创建一个影子页表,指向与主页表相同的页面。对磁盘上的临时空间进行修改后,影子表就会更新。要完成提交,数据库根指针将重定向到影子表,影子表将成为新的主表。
CMU15-445-Spring-2023-Project #4 - 前置知识(lec15-20)_第5张图片
影子分页的一个缺点是复制整个页表的成本很高。实际上,需要复制的只是树中通向更新叶节点的路径,而不是整个树。此外,影子分页的提交开销也很高。提交时,除了需要刷新页表和根节点外,还需要刷新每个更新的页面。这会导致数据碎片化,还需要进行垃圾回收。另一个问题是,影子分页每次只支持一个写入事务或批量事务

Journal File

当事务修改页面时,DBMS 会将原始页面复制到一个单独的日志文件,然后再覆盖主版本。重启后,如果存在日志文件,DBMS 就会恢复它,以撤销未提交事务的更改。

Write-Ahead Logging

通过 write-ahead logging,DBMS 会在对磁盘页面进行更改之前,将对数据库所做的所有更改记录在日志文件(稳定存储)中。日志中包含的信息足以在数据库崩溃后执行必要的撤销和重做操作来恢复数据库。DBMS 必须将与数据库对象所做更改相对应的日志文件记录写入磁盘,然后才能将该对象刷新到磁盘。WAL 是 STEAL + NO-FORCE 系统的一个示例。
CMU15-445-Spring-2023-Project #4 - 前置知识(lec15-20)_第6张图片
在shadow paging中,DBMS 需要对磁盘上的随机非连续页面执行写入操作。write-ahead logging 允许 DBMS 将随机写入转换为顺序写入,以优化性能。因此,几乎所有 DBMS 都使用WAL,因为它具有最快的运行时性能。但 DBMS 使用 WAL 的恢复时间比shadow paging慢,因为它必须重放日志。
DBMS 首先将事务的所有日志记录分阶段保存在易失性存储器中。然后,与更新页面相关的所有日志记录都会被写入非易失性存储空间,然后页面本身才会在非易失性存储空间中被覆盖。在所有日志记录都写入稳定存储器之前,事务不会被视为已提交。
当事务开始时,为每个事务向日志写入 记录,以标记其起点。
当事务结束时,向日志写入 记录,并确保在向应用程序返回确认之前刷新所有日志记录。
每个日志条目都包含对单个对象的更改进行倒带或重放所需的信息:
image.png
DBMS 必须将事务的所有日志条目刷新到磁盘上,然后才能向外界宣布事务已成功提交。系统可以使用 "分组提交" 优化功能,将多个日志刷新分批进行,以减少开销。日志刷新要么在日志缓冲区已满时进行,要么在连续刷新之间间隔足够长的时间后进行。
在日志结构 DBMS 中,事务日志记录被写入一个名为 MemTable 的内存缓冲区。 当该缓冲区满时,它就会被刷新到磁盘上。这种方法仍然需要一个独特的WAL。这是因为 WAL 的刷新通常比 MemTable 的刷新更频繁,而且 WAL 可能包含未提交的事务。在从崩溃中恢复时,WAL 用于重新创建内存中的 MemTable。

Logging Schemes

物理日志

  • 记录对数据库中特定位置所做的字节级更改。
  • Example: git diff

逻辑日志

  • 记录事务执行的高级操作。
  • 不一定仅限于一页。
  • 与物理日志记录相比,逻辑日志记录需要写入的数据更少,因为每条记录可以在多个页面上更新多个tuple。不过,恢复需要更长的时间,因为必须重新执行每个事务。
  • Example: The UPDATE, DELETE, and INSERT queries invoked by a transaction.

生理日志

  • 混合方法,日志记录以单个页面为目标,但不指定页面的数据组织。也就是说,根据页面中的槽号来识别tuple,而不指定更改在页面中的具体位置。因此,DBMS可以在日志记录写入磁盘后重新组织页面。
  • 最常用。

Checkpoints

基于 WAL 的 DBMS 的主要问题是日志文件会一直增长。崩溃后,DBMS 必须重放整个日志,如果日志文件很大,这可能需要很长时间。因此,DBMS 可以在所有缓冲区刷新到磁盘上时设置checkpoint。
阻塞检查点实现:

  • DBMS 停止接受新事务,等待所有活动事务完成。
  • 将当前驻留在主内存中的所有日志记录和脏块刷新到稳定存储区。
  • 向日志写入 条目并刷新到稳定存储区。

Lecture #20_ Database Crash Recovery

@# Crash Recovery

DBMS 依靠其恢复算法来确保数据库的一致性、事务原子性和故障后的持久性。每种恢复算法都由两部分组成:

  • 在正常事务处理期间采取的行动,以确保 DBMS 能够从故障中恢复。
  • 故障发生后采取的行动,以将数据库恢复到可确保事务的原子性、一致性和持久性的状态。

语义恢复和隔离算法(Algorithms for Recovery and Isolation Exploiting Semantics ARIES)是 IBM 在 20 世纪 90 年代初为 DB2 系统开发的一种恢复算法。

  • WAL:在将数据库更改写入磁盘之前,任何更改都会记录在稳定存储器的日志中(STEAL + NO-FORCE)
  • redo时回溯历史记录:重新启动时,回溯操作并将数据库恢复到崩溃前的准确状态。
  • 记录撤消过程中的更改:将撤消操作记录到日志中,确保在重复出现故障时不会重复操作。

WAL Records

WAL记录扩展了 DBMS 的日志记录格式,使其包含一个全局唯一的日志序列号 (LSN)。
CMU15-445-Spring-2023-Project #4 - 前置知识(lec15-20)_第7张图片
每个 WAL 都有一个 LSN 计数器,每一步都会递增。页面还会保存一个 pageLSN 和一个 recLSN,后者存储了导致页面变脏的第一条日志记录。flushedLSN 是指向最后写入磁盘的 LSN 的指针。MasterRecord 指向最后一次成功通过的检查点。
CMU15-445-Spring-2023-Project #4 - 前置知识(lec15-20)_第8张图片

Normal Execution

每个事务都会调用一系列读取和写入操作,然后提交或终止。恢复算法必须具备这种事件序列。
事务提交时,DBMS 会首先将 COMMIT 记录写入内存中的日志缓冲区。然后,DBMS 会将包括事务 COMMIT 记录在内的所有日志记录刷新到磁盘。请注意,这些日志刷新是顺序同步写入磁盘的。每个日志页可以有多个日志记录。一旦 COMMIT 记录安全地存储在磁盘上,DBMS 就会向应用程序返回事务已提交的确认信息。稍后,数据库管理系统会向日志写入一条特殊的 TXN-END 记录。这表明系统中的事务已完全结束,不会再有任何日志记录。这些 TXN-END 记录用于内部记账,不需要立即刷新。
CMU15-445-Spring-2023-Project #4 - 前置知识(lec15-20)_第9张图片
中止事务是 ARIES 撤消操作的一个特例,只适用于一个事务。 日志记录中会增加一个名为 prevLSN 的字段。它与事务的前一个 LSN 相对应。DBMS 使用这些 prevLSN 值来维护每个事务的链接列表,这样就能更方便地在日志中查找其记录。此外,还引入了补偿日志记录(compensation log record,CLR),描述了撤消前一条更新记录的操作。它包含更新日志记录的所有字段,外加 undoNext 指针(即下一个要撤销的 LSN)。DBMS 将 CLR 添加到日志中,就像添加其他记录一样,但它们永远不需要被撤销。要中止事务,DBMS 首先会在内存的日志缓冲区中添加一条 ABORT 记录。然后以相反的顺序撤销事务的更新,以消除它们对数据库的影响。对于每次撤销的更新,DBMS 都会在日志中创建 CLR 条目并恢复旧值。在撤销所有已中止事务的更新后,数据库管理系统会写入 TXN-END 日志记录。
CMU15-445-Spring-2023-Project #4 - 前置知识(lec15-20)_第10张图片

Checkpointing

DBMS 会定期checkpoint,将缓冲池中的脏页面写入磁盘。这样做的目的是尽量减少恢复时需要重放的日志内容。

  • Blocking Checkpoints
    • 会停止事务和查询的执行,以确保向磁盘写入一致的数据库快照。
  • Slightly Better Blocking Checkpoints
    • DBMS 会记录检查点开始时的内部系统状态。
    • 活动事务表 (ATT):ATT 表示 DBMS 中正在运行的事务的状态。DBMS 完成事务的提交/中止流程后,事务条目就会被删除。
    • 脏页面表 (DPT):DPT 包含缓冲池中被未提交事务修改的页面信息。每个脏页面都有一个包含 recLSN 的条目(即首先导致页面变脏的日志记录的 LSN)。
    • 总体而言,ATT 和 DPT 的作用是帮助 DBMS 通过 ARIES 恢复协议恢复数据库崩溃前的状态。
  • Fuzzy Checkpoints
    • 模糊检查点是指 DBMS 允许其他事务继续运行。这就是 ARIES 在其协议中使用的方式。
    • DBMS 使用额外的日志记录来跟踪检查点边界。和

ARIES Recovery

ARIES 协议的三个阶段:

  • Analysis:读取 WAL 以识别缓冲池中的脏页面和崩溃时的活动事务。在分析阶段结束时,ATT 会告诉 DBMS 崩溃时哪些事务处于活动状态。DPT 会告诉 DBMS 哪些脏页面可能没有存入磁盘。
    • 从通过数据库MasterRecord LSN 找到的最后一个检查点开始。
  • Redo: 从日志中的适当点开始重复所有操作。
    • 此阶段的目标是让 DBMS 重复历史记录,重建崩溃前的状态。DBMS 会从 DPT 中包含最小 recLSN 的日志记录开始向前扫描。对于具有给定 LSN 的每条更新日志记录或 CLR,DBMS 都会重新应用更新。
    • 要redo操作,DBMS 会在日志记录中重新应用更改,然后将受影响页面的 pageLSN 设置为该日志记录的 LSN。 在重做阶段结束时,为所有状态为 COMMIT 的事务写入 TXN-END 日志记录,并将其从 ATT 中删除。
  • Undo:撤销崩溃前未提交的事务操作。
    • 在最后一个阶段,DBMS 会撤销崩溃时处于活动状态的所有事务。
    • DBMS 会使用 lastLSN 按 LSN 倒序处理事务,以加快遍历速度。在反向更新事务的过程中,DBMS 会为每次修改向日志写入 CLR 条目。
    • 一旦最后一个事务被成功中止,DBMS 就会清空日志,然后准备开始处理新事务。

CMU15-445-Spring-2023-Project #4 - 前置知识(lec15-20)_第11张图片

你可能感兴趣的:(Linux服务器编程,数据库,cmu15445,笔记)