openGauss源码解析(67)
openGauss源码解析:存储引擎源码解析(35)
4.3.9 恢复
恢复部分有两个目的,一是在崩溃或关机后达到最新的一致状态,也称为冷启动(coldstart),二是在HA复制场景中,在备机侧通过重放redo log完成复制。
冷启动时,当所有WAL记录都重放完成后恢复结束;但在HA复制场景中,复制将持续进行,直到备机改变状态。
在恢复过程中,可能存在跨越多个重做日志段的长事务,MOT将其保存在InProcessTransactions映射对象中,直到提交。包含在映射中的数据作为检查点处理过程的一部分进行序列化,并在检查点恢复期间进行反序列化。
此外,在最后恢复阶段,完成所有检查点/WAL记录之后将设置最后的CSN,并将代理键生成器恢复到崩溃或关闭前的最新状态。
为了恢复代理状态,每个恢复线程(检查点和重做日志)都在更新每个线程id的代理最大键数组。最后,这些数组被合并成单个数组,用于恢复最后状态。
1. 详细流程
具体恢复流程如图4-72所示。
恢复过程如下。
(1) 通过openGauss的StartupXLOG函数调用MOT恢复过程。
(2) 如果存在检查点则从检查点执行第一次恢复。
(3) 读取控制文件,并获取重放lsn。当重启点(备机检查点)存在时,将使用lastReplayLsn作为重放点,而非lsn。
(4) 处理检查点映射文件并生成任务列表。由于MOT检查点仅由行组成,不需要以特定顺序重放,因此这些行的恢复可以并行执行。这就是检查点进程将表拆分成段的原因。
(5) 从元数据文件中恢复所有表的元数据。
(6) 创建检查点恢复线程,每个线程尝试从列表中获取任务,读取与此任务关联的文件并恢复行数据。此恢复是非事务性的。
(7) 如果有进程内事务,也会从检查点恢复。
(8) 检查点恢复完成,返回StartupXLOG,开始重放redo记录。
(9) 当遇到MOT资源管理器(resource manager,rmgr)记录时,将调用MOT引擎的MOTRedo函数,该函数调用恢复管理器ApplyRedoRecord方法。
(10) 在ApplyRedoRecord中,只有当数据的lsn大于恢复的检查点lsn,并且调用ApplyLogSegmentFromData时,才会处理数据。
(11) ApplyLogSegmentFromData从数据中提取LogSegment,分配并插入InProcessTransactions Map。
(12) 当遇到提交记录时,该记录可以是仅MOT事务的LogSegment的一部分,也可以来自MOT注册到openGauss的DDL或跨引擎事务的提交后回调。事务的相关日志段将进行事务性重放和提交。
(13) 上述过程将继续循环,直到StartupXLOG完成。
(14) 调用RecoverDbEnd完成恢复,设置CSN并应用代理状态。
2. 关键类和数据结构
恢复的关键类和数据结构如表4-41所示。
表4-41 关键类和数据结构简介
关键类和数据结构 | 描述 |
RecoveryManager | 实现了IRecoveryManager的API,它是恢复中使用的主类 |
IRecoveryManager | 是一个抽象类,定义了每个RecoveryManager应该实现的接口 |
SurrogateState | 保存了内部数组中每个连接ID的代理键值 |
LogStats | 用于统计,统计信息在LogStats::Entry中按表收集,需在mot.conf中启用 |
CheckpointRecovery | 负责从有效的检查点恢复所有行。它封装了恢复所需的所有操作,包括表的元数据和并行行插入 |
LogSegment | 实际上是重做日志保存的数据段,除了缓冲区外还包括描述操作及其事务ID的元数据 |
RedoLogTransactionSegment | 多个日志段的容器,可以形成一个完整的事务 |
RedoLogTransactionIterator | 一个从XLOG数据中提取LogSegments的helper类 |
InProcessTransactions | 单例模式的Map对象,用于保留正在运行的事务LogSegments,并一直收集直到这些事务提交为止 |
RecoveryOps | 从LogSegment执行DML和DDL操作的实际恢复 |
4.4 小结
本章主要介绍了openGauss的存储引擎,包括磁盘引擎和内容表。在磁盘引擎中,openGauss提供不同存储格式的磁盘引擎来满足不同业务场景对于数据不同的访问和使用模式。内存表针对众核和大内存服务器进行了优化,可提供非常高的事务性工作负载性能。