openGauss源码解析(63)
openGauss源码解析:存储引擎源码解析(31)
4.3.7 重做日志
MOT重做日志(Redo Log)使用预写式日志(write-ahead logging,WAL)技术来确保数据完整性。WAL的核心概念是,内存中的数据和索引的更改只有在记录下这些更改之后才会发生。因此写入重做日志是MOT提交协议的一部分。
如图4-63所示,MOT存储引擎的重做日志模块同样使用openGauss磁盘引擎的日志接口进行持久化和恢复。这意味着MOT重做数据被写入相同的XLOG文件,并使用相同的XLOG逻辑。使用与openGauss磁盘引擎相同的日志记录接口可确保跨引擎事务的一致性,并减少复制、日志恢复等模块的冗余实现。
图4‑63 使用相同的XLOG (WAL)基础架构的openGauss磁盘库和MOT
1. 事务日志记录
与openGauss其他存储引擎不同,MOT内存引擎仅在事务实际提交时才会写入重做日志。因此,在事务期间或事务中止时,数据不会写入重做日志。这样可以减少写入的数据量,从而减少不必要的磁盘IO调用,因为这种磁盘IO调用很慢。例如,如果在事务期间多次更新同一行,则只将表示已提交行的最终状态写入日志。
由于设计MOT内存引擎时考虑了对接不同的数据库的可能性,因此如图4-64所示,MOT通过抽象的ILogger接口对接重做日志。
图4‑64 ILogger接口
2. 日志类型
设计MOT内存引擎时同样考虑了支持不同的日志记录方式。如图4-65所示,MOT当前已实现同步日志(synchronous redo Log)和同步组日志(group synchronous redo log)。这是通过RedoLogHandler类实现的。RedoLogHandler封装了日志逻辑,在数据库启动时初始化。RedoLogHandler可以根据需要扩展实现新的日志记录方式。
每个事务管理器对象(TxnManager)都包含一个Redolog类,该类负责在提交时将事务数据序列化到缓冲区中。如图4-66所示,该缓冲区被传输到RedologHandler以进行日志记录。
1) 同步日志记录
同步日志使用SynchronousRedoLogHandler。如图4-67所示,这是一个简单的RedoLogHandler实现,它只将序列化缓冲区委托给ILogger(XLOGLogger),以便将其写入XLOG。因为在写缓冲区时,事务被阻塞,所以称为同步。只有当所有事务数据被序列化并写入日志时,提交协议才会继续。
图4‑67 SynchronousRedoLogHandler
2) 同步组提交日志记录
同步组提交日志由SegmentedGroupSyncRedoLogHandler类实现。它通过将几个事务分组到一个写块(write block)中并一起写入的方式优化日志记录。这种方法在一次调用中收集更多数据,可以最大限度地减少磁盘IO次数。除此之外, SegmentedGroupSyncRedoLogHandler将每个NUMA处理器(socket)的事务分组,以减少跨NUMA处理器的数据传输,因为跨NUMA处理器的数据访问比同一NUMA处理器本地内存访问慢。
当事务提交时,它将数据序列化到缓冲区中,这个缓冲区被传输到SegmentedGroupSyncRedoLogHandler,并放入一个提交组中。提交组(Commit Group)是一组序列化事务缓冲区的集合,这些事务缓冲区将被提交并写入磁盘。根据不同的配置参数,当一个组被填满或超过预先配置的时间时,MOT将关闭该组,并将该组内所有缓冲区一起写入日志。
图4-68描述了将多个事务分组一起写入的组提交逻辑。
3) 异步日志
MOT暂未开发专用的异步日志机制,异步日志是通过在conf配置文件中将synchronization_commit参数设置为“off”来实现的。