存储引擎源码解析 | 磁盘引擎(8)

3. 回滚段设计与MVCC
1) 回滚段
旧版本数据会集中在回滚段的undo目录中,为了减少读写冲突,旧版本数据(回滚记录)采用追加写的方式写入数据目录的undo目录下。这样旧版本数据的读取和写入不会发生冲突,同一个事务的旧版本数据也会连续存放,便于进行回滚操作。为了减少并发写入时的竞争,undo目录空间被划分成多个逻辑区域(UndoZone,回滚段逻辑区域)。线程会在自己的逻辑区域上进行分配,与其他线程完全隔离,从而写入旧数据分配空间时就不会有额外的锁开销。UndoZone还可以按照CPU的NUMA核进行划分,每个线程会从当前的NUMA核上的UndoZone进行分配,进一步提升分配效率。在分配undo空间时会按照事务粒度进行记录,旧版本数据一旦确认没有事务进行访问,就会进行回收。
为了在回滚段的空间寻址,回滚记录使用8字节的指针来进行寻址,如图4-14所示。

其中各个字段的含义如下:
(1) zoneId:占用20bit,表示逻辑区域的ID。
(2) blockId:占用31bit,表示块号,默认为8k。
(3) offset:占用13bit,表示块内偏移。
旧版本的数据采用回滚记录的格式存入回滚段中,其中回滚记录的格式如下所示:

… UndoRecordHeader whdr_; UndoRecordBlock wblk_; UndoRecordTransaction wtxn_; UndoRecordPayload wpay_; UndoRecordOldTd wtd_; UndoRecordPartition wpart_; UndoRecordTablespace wtspc_; StringInfoData rawdata_; }