openGauss源码解析(84)
openGauss源码解析:事务机制源码解析(15)
4. CLOG Partition优化
CLOG日志即是事务提交日志(详情可参考章节“5.2.2 事务ID分配及CLOG/CSNLOG)”,每个事务存在4种状态:IN_PROGRESS、COMMITED、ABORTED、SUB_COMMITED,每条日志占2 bit。CLOG日志需要存储在磁盘上,一个页面(8kB)可以包含215条,每个日志文件(段=256 x 8k)226条。当前CLOG的访问通过缓冲池实现,代码中使用统一的SLRU缓冲池算法。
图5-22 CLOG的日志缓冲池优化前
图5-23 CLOG的日志缓冲池优化后
如图5-22所示,CLOG的日志缓冲池在共享内存中且全局唯一,名称为名称为“CLOG Ctl”,为各工作线程共享该资源。在高并发的场景下,该资源的竞争成为性能瓶颈,优化分区后如图5-23。按页面号进行取模运算(求两个数相除的余数)将日志均分到多个共享内存的缓冲池中,由线程局部对象的数组ClogCtlData来记录,名称为“CLOG Ctl i”,同步增加共享内存中的缓冲池对象及对应的全局锁。也就是通过打散的方式提高整体吞吐。
CLOG分区优化需要将源代码中涉及原缓冲池的操作进行修改,改为操作对应的分区的缓冲池,而通过事务id、页面号能方便地找到对应的分区,与此同时对应的控制锁也从原来的一把锁改为多把锁的操作,涉及的结构体代码如下,涉及的函数如表5-8所示:
/* CLOG分区*/
#define NUM_CLOG_PARTITIONS 256 /*分区打散的个数*/
/* CLOG轻量级分区锁*/
#define CBufHashPartition(hashcode) \
((hashcode) % NUM_CLOG_PARTITIONS)
#define CBufMappingPartitionLock(hashcode) \
(&t_thrd.shemem_ptr_cxt.mainLWLockArray[FirstCBufMappingLock + CBufHashPartition(hashcode)].lock)
#define CBufMappingPartitionLockByIndex(i) \
(&t_thrd.shemem_ptr_cxt.mainLWLockArray[FirstCBufMappingLock + i].lock)
表5-8 CLOG分区优化函数
函数名 |
简述 |
CLOGShmemInit |
调用SimpleLruInit 初始化共享内存中的CLOG缓冲区 |
ZeroCLOGPage |
CLOG日志页面的初始化为0 |
BootStrapCLOG |
创建数据库时,在缓冲区中创建初始可用的CLOG日志页面,并调用 ZeroCLOGPage初始化页面为0,写回到磁盘,并返回页面 |
CLogSetTreeStatus |
设置事务提交的最终状态 |
CLogGetStatus |
查询事务状态 |
ShutdownCLOG |
关闭缓冲区,刷新到磁盘中 |
ExtendCLOG |
为新分配的事务,创建CLOG页面 |
TruncateCLOG |
日志检查点的建立使得部分事务的日志过期,可删除以节省空间 |
WriteZeroPageXlogRec |
新建XLOG页面时,写“CLOG_ZEROPAGE” XLOG日志,以便将来恢复使用 |
clog_redo |
CLOG日志相关的 redo 操作,含CLOG_ZEROPAGE及CLOG_TRUNCATE |