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

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

wukong 2024-09-19
50

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

背景

本文主要针对海山数据库中CLOG日志管理器部分关键函数源码进行研读。主要涉及ExtendCLOG、TruncateCLOG

ExtendCLOG

背景:
为新分配的事务ID创建CLOG 日志空间。当一个事务的 CLOG 日志记录位于一个CLOG日志页面的首部时,若这个事务要写一条CLOG 日志记录,就需要调用 ExtendCLOG 以创建一个新的CLOG 日志页面供该条CLOG日志记录写入

void ExtendCLOG(TransactionId newestXact) { int pageno; /* * No work except at first XID of a page. But beware: just after * wraparound, the first XID of page zero is FirstNormalTransactionId. */ if (TransactionIdToPgIndex(newestXact) != 0 && !TransactionIdEquals(newestXact, FirstNormalTransactionId)) return; pageno = TransactionIdToPage(newestXact); LWLockAcquire(XactSLRULock, LW_EXCLUSIVE); /* Zero the page and make an XLOG entry about it */ ZeroCLOGPage(pageno, true); LWLockRelease(XactSLRULock); }

void ExtendCLOG(TransactionId newestXact)
  • newestXact表示最新的事务id

if (TransactionIdToPgIndex(newestXact) != 0 && !TransactionIdEquals(newestXact, FirstNormalTransactionId)) return;

判断新事务id是不是新页面的第一个事务id:

  • TransactionIdToPgIndex(newestXact) 将新事务id转换为CLOG中页面的索引,如果结果不为0,说明这不是新页面的开始
  • 其次检测newestXact是否不等于FirstNormalTransactionId,这是因为在事务ID回绕(wraparound)之后,第一个页面的第一个事务ID将是 FirstNormalTransactionId。如果这两个条件都不满足,函数将直接返回,不做任何操作。

pageno = TransactionIdToPage(newestXact);

  • 计算新事务id对应的页号

LWLockAcquire(XactSLRULock, LW_EXCLUSIVE); ZeroCLOGPage(pageno, true); LWLockRelease(XactSLRULock);
  • 获取名为XactSLRULock的轻量级排他锁
  • 调用ZeroCLOGPage函数将页号为pageno的页面清零,并设置第二个参数为true以指示需要记录xlog日志
    • 这意味着该操作将在 PostgreSQL 的写前日志(WAL)中留下记录,以确保在系统崩溃后能够恢复。
  • 释放轻量级锁

TruncateCLOG

作用:删除过时的CLOG日志记录,以节省磁盘空间并优化性能

源码:

void TruncateCLOG(TransactionId oldestXact, Oid oldestxid_datoid) { int cutoffPage; cutoffPage = TransactionIdToPage(oldestXact); /* Check to see if there's any files that could be removed */ if (!SlruScanDirectory(XactCtl, SlruScanDirCbReportPresence, &cutoffPage)) return; /* nothing to remove */ /* * Advance oldestClogXid before truncating clog, so concurrent xact status * lookups can ensure they don't attempt to access truncated-away clog. * * It's only necessary to do this if we will actually truncate away clog * pages. */ AdvanceOldestClogXid(oldestXact); /* * Write XLOG record and flush XLOG to disk. We record the oldest xid * we're keeping information about here so we can ensure that it's always * ahead of clog truncation in case we crash, and so a standby finds out * the new valid xid before the next checkpoint. */ WriteTruncateXlogRec(cutoffPage, oldestXact, oldestxid_datoid); /* Now we can remove the old CLOG segment(s) */ SimpleLruTruncate(XactCtl, cutoffPage); }

int cutoffPage; cutoffPage = TransactionIdToPage(oldestXact);

计算旧事务idoldestXact对应的CLOG页面号,并赋给cutoffPage


if (!SlruScanDirectory(XactCtl, SlruScanDirCbReportPresence, &cutoffPage)) return;

使用SlruScanDirectory 函数和回调函数 SlruScanDirCbReportPresence ,以cutoffPage页面为参照,扫描 CLOG 目录,以检查是否有文件可以被移除。如果没有文件可以移除(即没有早于cutoffPage 的页面),则函数直接返回。


AdvanceOldestClogXid(oldestXact);

在截断 CLOG 之前,通过 AdvanceOldestClogXid 函数更新 oldestClogXid,确保并发事务状态查找不会尝试访问已截断的 CLOG 页面。


WriteTruncateXlogRec(cutoffPage, oldestXact, oldestxid_datoid);

通过WriteTruncateXlogRec 函数写入一个 XLOG 记录,记录截断操作的截断点和最旧事务ID。这是为了确保在系统崩溃或恢复时,可以正确地恢复 CLOG 状态。


SimpleLruTruncate(XactCtl, cutoffPage);

使用 SimpleLruTruncate 函数实际执行截断操作,移除早于 cutoffPage 的 CLOG 页面

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

评论