4.3.8 检查点
与openGauss磁盘存储引擎不同,MOT存储引擎不基于页面存储数据,因此MOT的检查点机制与磁盘引擎的检查点机制完全不同。MOT检查点机制基于CALC(checkpointing asynchronously using logical consistency,使用逻辑一致性异步检查点)算法,该算法出自耶鲁大学Kun Ren等人在数据库顶级会议SIGMOD 2016发表的《Low-Overhead Asynchronous Checkpointing in Main-Memory Database Systems》。
1. CALC算法
CALC算法的优点如下。
(1) 内存占用少:任意时刻每行最多2个副本。只有当检查点为活动状态时,更具体地说,仅在检查点的一个特定阶段,才会创建第二个副本,从而减少了内存占用。
(2) 开销小:CALC比其他异步检查点算法开销小。
(3) 使用虚拟一致性点:CALC不需要停止数据库就能实现物理一致性。虚拟一致性点是数据库的视图,它反映了在指定时间之前提交的所有修改,而不包含指定时间之后提交的修改,而且在不停止数据库系统的情况下就可以获得。实际上,可以通过部分多版本创建虚拟一致性点。
如图4-70所示,精确部分多版本算法(precise partial multi-versioning)的总体思想如下。
(1) 每行都与两个版本相关联,一个是活动版本,一个是稳定版本。通常,稳定版本为空,表明稳定版本与活动版本一致,检查点线程可以安全地记录实时版本。稳定版本仅在检查点的一个特定阶段创建,此时检查点线程将记录该稳定版本。
(2) 每行维护一个稳定状态位,指示稳定行的状态。
图4-70 检查点概述
MOT检查点算法在五个状态之间循环,如图4 71所示。
图471 检查点状态机
通常,在进入下一阶段之前,系统要等待所有上一阶段开始提交的事务完成。
1) REST阶段:初始阶段,不进行checkpoint。
(1) 在REST阶段,每行只存储一个活动版本。所有稳定版本都为空,稳定状态位始终为不可用(not available)。
(2) 在此阶段开始提交的任何事务将直接对行的活动版本进行操作,并且不会创建稳定版本。
2) PREPARE阶段:这是虚拟一致性点之前的阶段。当openGauss要求MOT创建快照时,系统从REST阶段移动到PREPARE阶段。
(1) 与REST阶段类似,每行只存储一个活动版本。所有稳定版本都为空,稳定状态位始终为不可用。
(2) 在此阶段开始提交的任何事务将直接对行的活动版本进行操作,不会创建稳定版本。
3) RESOLVE阶段:该阶段标识出虚拟一致性点。在此时间点之前提交的所有事务都将包含在此检查点中,而随后提交的事务将不包含在检查点中。一旦在REST阶段开始提交的事务完成,系统将自动从REST阶段变为RESOLVE阶段。
(1) 在此阶段不允许任何事务启动提交,以避免这些事务在openGauss占用检查点的重做点前写入重做日志。
(2) 一旦在REST阶段开始提交的事务完成,MOT将在此阶段获取要包含在此检查点中的任务列表。
4)CAPTURE阶段:在此阶段中,后台工作进程将数据刷入磁盘。RESOLVE阶段一直持续,直到在准备阶段已开始的所有事务完成并释放其所有锁为止。系统准备任务列表,然后进入CAPTURE阶段。
(1) 在CAPTURE阶段开始的事务已经在一致性点之后开始,因此他们肯定会在一致性点之后完成。因此,除非记录已经具有显式稳定版本,否则总是在更新前将活动版本复制为对应的稳定版本。
(2) 收到BEGIN_CHECKPOINT事件后,系统生成检查点工作进程,扫描所有记录,并将没有显式稳定版本的行,或活动版本的对应的稳定版本刷盘。在此过程中,显式稳定版本一旦刷盘就会被释放。
5) COMPLETE阶段:这是紧跟捕获阶段完成的阶段。检查点捕获完成后,系统进入COMPLETE阶段。事务写入行为恢复为与REST阶段相同的状态。
与REST阶段类似,每行只存储一个活动版本。所有稳定版本都为空,稳定状态位始终为不可用(not available)。
一旦在捕获阶段开始的所有事务都完成,系统将转换回REST阶段,并等待下一个触发检查点的信号。但是,在返回到REST阶段之前,调用函数SwapAvailableAndNotAvailable翻转稳定状态位。这允许MOT避免只能通过完全扫描来重置稳定状态位,因为在CAPTURE阶段之后,所有稳定状态位都可用,但在Rest阶段开始时,希望所有稳定状态位都不可用。
2. 详细流程
(1) 一旦触发了检查点,Checkpointer后台会触发MOT的CREATE_SNAPSHOT事件。
(2) 当检查点处于REST阶段时,CheckpointManager将等待在COMPLETE阶段启动的事务完成。
(3) CheckpointManager修改checkpoint阶段为PREPARE。如果没有在REST阶段启动提交的事务处于活动状态,则立即进入RESOLVE阶段,否则等待REST阶段启动提交的最后一个事务完成后进入RESOLVE阶段。
(4) RESOLVE阶段标记了虚拟一致性点。在此阶段不允许任何事务开始提交,以避免在openGauss采取检查点的重做点之前这些事务写入重做日志。CheckpointManager等待在PREPARE阶段启动的事务完成。
(5) CheckpointManager准备要flush的表的列表(任务列表)并读取这些表的锁状态。
(6) 然后获取写锁,锁定redolog handler,并将检查点阶段更改为CAPTURE。这标志着CREATE_SNAPSHOT事件结束。
(7) openGaussCheckpointer获取WalInsertLock锁并计算此检查点的重做点。然后,该重做点触发MOT的SNAPSHOT_READY事件。
(8) CheckpointManager存储重做点,释放redolog handler锁。这标志着SNAPSHOT_READY事件结束。
(9) 然后openGaussCheckpointer释放WalInsertLock并将所有磁盘引擎脏页刷盘,即磁盘引擎的检查点。
(10) 然后触发MOT的BEGIN_CHECKPOINT事件。
(11) CheckpointManager在这个阶段生成检查点worker来完成MOT检查点任务列表。
(12) 检查点worker之间共享任务列表,并将所有符合条件的行刷入磁盘(行的稳定版本或没有显式稳定版本到磁盘的活动版本)。在此过程中任何显式稳定版本一旦刷新到磁盘,就会释放。
(13) 一旦所有检查点worker完成任务,CheckpointManager将解锁表并清除任务列表。
(14) CheckpointManager还可将检查点阶段提前到COMPLETE。
(15) 通过创建map文件、结束文件等来完成检查点,然后更新mot.ctrl文件。
(16) 等待CAPTURE阶段开始的事务完成。
(17) 交换可用位和不可用位,以便将他们映射到稳定状态位中的1和0值。
(18) 修改checkpoint阶段为REST。这标志着BEGIN_CHECKPOINT事件和MOT检查点的结束。
(19) 然后openGauss将检查点记录插入到XLOG中,刷新到硬盘,最后更新控制文件。openGauss中的检查点就此结束。
3. 关键类和数据结构
检查点的关键类和数据结构如表4-40所示。