海山数据库(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进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




