暂无图片
暂无图片
1
暂无图片
暂无图片
暂无图片

海山数据库(He3DB)源码详解:He3DB-CLOG日志管理器函数之CLOGShmemInit、ZeroCLOGPage

He3DB_ht 2024-10-10
48

海山数据库(He3DB)源码详解:He3DB-CLOG日志管理器函数之CLOGShmemInit、ZeroCLOGPage

0 背景

He3DB 采用了先进的存储引擎和查询优化技术,能够快速处理大量数据和复杂查询。无论是 OLTP(在线事务处理)还是 OLAP(在线分析处理)场景,都能提供出色的性能表现。He3DB 具备完善的数据备份和恢复机制,能够在系统故障或数据损坏时快速恢复数据,确保业务的连续性。He3DB 支持水平扩展和垂直扩展,可以轻松应对不断增长的数据需求。He3DB 提供了严格的访问控制和数据加密功能,确保数据的安全性和隐私性。

本文基于He3DB,针对CLOG日志管理模块进行源码解读分享,包含CLOGShmemInit、ZeroCLOGPage两个函数

1 CLOGShmemInit源码解析

void CLOGShmemInit(void) { XactCtl->PagePrecedes = CLOGPagePrecedes; SimpleLruInit(XactCtl, "Xact", CLOGShmemBuffers(), CLOG_LSNS_PER_PAGE, XactSLRULock, "pg_xact", LWTRANCHE_XACT_BUFFER, SYNC_HANDLER_CLOG); SlruPagePrecedesUnitTests(XactCtl, CLOG_XACTS_PER_PAGE); }

XactCtl->PagePrecedes = CLOGPagePrecedes;

  • CLOGPagePrecedes 函数
static bool CLOGPagePrecedes(int page1, int page2) { TransactionId xid1; TransactionId xid2; xid1 = ((TransactionId) page1) * CLOG_XACTS_PER_PAGE; xid1 += FirstNormalTransactionId + 1; xid2 = ((TransactionId) page2) * CLOG_XACTS_PER_PAGE; xid2 += FirstNormalTransactionId + 1; return (TransactionIdPrecedes(xid1, xid2) && TransactionIdPrecedes(xid1, xid2 + CLOG_XACTS_PER_PAGE - 1)); }

计算两个页面各自的起始xid

  • 通过将page1强制转换为TransactionId类型(uint32)数据,并乘以每页事务数量CLOG_XACTS_PER_PAGE
  • 再加上一个正常事务ID

通过TransactionIdPrecedes比较,来判断page1和page2哪个页面再截断过程(快速删除表中数据)中被认为是更旧的

若返回true,表示xid1在xid2之前,表示page1在截断过程中被认为更旧
截断过程(快速删除表中数据),相比于DELETE操作更快。

理解为:因为要初始化,所以要清空的操作。此外,判断两个页面的新旧,是为了SLRU算法服务

SimpleLruInit(XactCtl, "Xact", CLOGShmemBuffers(), CLOG_LSNS_PER_PAGE, XactSLRULock, "pg_xact", LWTRANCHE_XACT_BUFFER, SYNC_HANDLER_CLOG);

调用SimpleLruInit函数初始化CLOG缓冲池,包括设置缓存的名称、缓冲区数量、每页LSN数量、锁定函数、文件名、锁事务号以及同步处理程序的标识符

SlruPagePrecedesUnitTests(XactCtl, CLOG_XACTS_PER_PAGE);

#define SlruPagePrecedesUnitTests(ctl, per_page) do {} while (0)

该函数是一个宏定义,但没有实质性操作,或许是未来要用于扩展单元测试代码

1.1 调用栈

该函数总体调用栈如图所示

image.png

1.1.1 被调关系

image1.png

CLOGShmemInitCreateSharedMemoryAndSemaphores函数调用,该函数用于创建和初始化共享内存以及信号量

1.1.2 调用关系

image2.png

  1. CLOGShmemBuffers函数
Size CLOGShmemBuffers(void) { LOG_FUNCTION_ENTRY(); LOG_FUNCTION_EXIT(); return Min(128, Max(4, NBuffers / 512)); }

用于计算CLOG缓存量buffers,采用的公式Min(128, Max(4, NBuffers / 512))是一种合理的折衷方案,对于共享缓冲区(shared_buffers)值非常低的用户,CLOG 缓冲区数量也会相应减少,而其他用户将获得 128 个缓冲区。

  1. SimpleLruInit函数

用于初始化或连接到共享内存中的一个简单最近最少使用(LRU)缓存

void SimpleLruInit(SlruCtl ctl, const char *name, int nslots, int nlsns, LWLock *ctllock, const char *subdir, int tranche_id, SyncRequestHandler sync_handler) {}
  1. SlruPagePrecedesUnitTests函数

用于对页面的前置关系函数进行单元测试

void SlruPagePrecedesUnitTests(SlruCtl ctl, int per_page) { LOG_FUNCTION_ENTRY(); /* Test first, middle and last entries of a page. */ SlruPagePrecedesTestOffset(ctl, per_page, 0); SlruPagePrecedesTestOffset(ctl, per_page, per_page / 2); SlruPagePrecedesTestOffset(ctl, per_page, per_page - 1); LOG_FUNCTION_EXIT(); return; }
  1. CLOGPagePrecedes函数用于判断一个CLOG页面编号在截断操作中是否 “更旧”。
static bool CLOGPagePrecedes(int page1, int page2) {}
  1. LOG_FUNCTION_ENTRY以及LOG_FUNCTION_EXIT用于记录函数开始和结束,用于调试定位

2 ZeroCLOGPage函数

注意:

  • 缓冲池和页面槽号:

    • 缓冲池是数据库管理系统用于缓存数据页面的内存区域。它允许数据库引擎在内存中操作数据,而不必每次都从磁盘读取。
    • 缓冲池中的每个槽对应一个页面。槽号是用于标识页面在缓冲池中位置的索引。不同的槽号对应不同的页面。
static int ZeroCLOGPage(int pageno, bool writeXlog) { int slotno; slotno = SimpleLruZeroPage(XactCtl, pageno); if (writeXlog) WriteZeroPageXlogRec(pageno); return slotno; }
  • 函数参数含义
    • pageno 表示要初始化的页面编号
    • writeXlog 如果为真,则会记录一个 XLOG 记录
slotno = SimpleLruZeroPage(XactCtl, pageno);
  • 根据XactCtl中的事务信息选择合适的页面槽号
  • 将页面编号为pageno的CLOG页面设置为零,并返回一个新页面的槽号,赋值给slotno
if (writeXlog) WriteZeroPageXlogRec(pageno);

如果writeXlog为true,调用WriteZeroPageXlogRec函数,在已经被设置为零且编号为 pageno的页面记录一条XLOG记录

一个缓冲池中有许多CLOG页面,不同的槽号对应不同的CLOG页面,然后WriteZeroPageXlogRec函数是将XLOG记录写在编号为pageno的CLOG页面上

最后,返回新页面的槽号

2.1 调用栈

image3.png

3 总结

函数名 作用
CLOGShmemInit CLOG日式管理器的初始化,用于在共享内存中初始化CLOG缓冲池
ZeroCLOGPage 将CLOG页面初始化或者重新初始化为零
CreateSharedMemoryAndSemaphores 用于创建和初始化共享内存以及信号量
SimpleLruInit 用于初始化或连接到共享内存中的一个简单最近最少使用(LRU)缓存
CLOGShmemBuffers 用于计算CLOG缓存量buffers
SlruPagePrecedesUnitTests 用于对页面的前置关系函数进行单元测试
CLOGPagePrecedes 函数用于判断一个CLOG页面编号在截断操作中是否 “更旧”
LOG_FUNCTION_ENTRY 用于记录函数开始
LOG_FUNCTION_EXIT 用于记录函数结束

4 He3DB其余文章参考链接

海山数据库(He3DB)源码详解:He3DB-CLOG日志管理器函数之TransactionIdSetTreeStatus

海山数据库(He3DB)+AI(五):一种基于强化学习的数据库旋钮调优方法

海山数据库(He3DB)+AI(四):一种基于迁移学习的启发式数据库旋钮调优方法

海山数据库(He3DB)源码解读:海山PG 词法、语法分析

海山数据库(He3DB)源码详解:海山PG 空闲空间映射表FSM

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论