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

海山数据库(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 页面

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值