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

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

处理事务日志重做过程中的一部分,专门用于处理clog记录。它负责处理两种类型的clog记录:ZEROPAGE和TRUNCATE,分别用于清零clog页面和截断事务控制信息的LRU缓存。

void
clog_redo(XLogReaderState *record)
{
	uint8		info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;

	/* Backup blocks are not used in clog records */
	Assert(!XLogRecHasAnyBlockRefs(record));

	if (info == CLOG_ZEROPAGE)
	{
		int			pageno;
		int			slotno;

		memcpy(&pageno, XLogRecGetData(record), sizeof(int));

		LWLockAcquire(XactSLRULock, LW_EXCLUSIVE);

		slotno = ZeroCLOGPage(pageno, false);
		SimpleLruWritePage(XactCtl, slotno);
		Assert(!XactCtl->shared->page_dirty[slotno]);

		LWLockRelease(XactSLRULock);
	}
	else if (info == CLOG_TRUNCATE)
	{
		xl_clog_truncate xlrec;

		memcpy(&xlrec, XLogRecGetData(record), sizeof(xl_clog_truncate));

		AdvanceOldestClogXid(xlrec.oldestXact);

		SimpleLruTruncate(XactCtl, xlrec.pageno);
	}
	else
		elog(PANIC, "clog_redo: unknown op code %u", info);
}

void
clog_redo(XLogReaderState *record)

该函数接收一个指向XLogReaderState结构体的指针record。该结构体包含了当前正在处理的WAL记录的信息


uint8		info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;

使用XLogRecGetInfo函数从record中获取WAL记录的信息,并通过与~XLR_INFO_MASK进行位与操作来清除一些不需要的位,结果存储在info变量中


Assert(!XLogRecHasAnyBlockRefs(record));

确保当前的CLOG记录不使用备份块(Backup blocks)

备份块:为了保持数据的一致性,在更改实际数据之前先对其进行备份的块

然而,在clog记录的情况下,这种备份机制不是必需的,因为clog本身就是一种记录事务更改的机制


if (info == CLOG_ZEROPAGE)
{
	int			pageno;
	int			slotno;

	memcpy(&pageno, XLogRecGetData(record), sizeof(int));

	LWLockAcquire(XactSLRULock, LW_EXCLUSIVE);

	slotno = ZeroCLOGPage(pageno, false);
	SimpleLruWritePage(XactCtl, slotno);
	Assert(!XactCtl->shared->page_dirty[slotno]);

	LWLockRelease(XactSLRULock);
}

如果获取的infoCLOG_ZEROPAGE

  • 调用memcpy函数。将 WAL 记录中的数据部分(具体来说是一个整型值,即页面编号)复制到变量 pageno 中。这样,pageno 就包含了需要从 WAL 记录中恢复的页面编号
  • &pageno 是目标内存地址,即变量 pageno 的地址。
  • XLogRecGetData(record) 是源内存地址,它返回一个指向 WAL 记录数据部分的指针。
  • sizeof(int) 是要复制的字节数,这里是一个整型的大小。
  • 获取排他锁
  • 将指定页面号的CLOG页面清零,并返回该页面对应的槽位号,此过程不需要xlog记录(第二个参数false)
  • 将修改后的slotno对应的页面写回LRU缓存
  • 断言。确保slotno对应的页面在 LRU 缓存中不再被标记为脏页面,如果仍然是脏页面,说明前面有问题
  • 释放锁

else if (info == CLOG_TRUNCATE)
{
	xl_clog_truncate xlrec;

	memcpy(&xlrec, XLogRecGetData(record), sizeof(xl_clog_truncate));

	AdvanceOldestClogXid(xlrec.oldestXact);

	SimpleLruTruncate(XactCtl, xlrec.pageno);
}

xl_clog_truncate定义了用于存储从 WAL记录中读取的截断信息的数据结构。包含要截断到的最旧事务ID(oldestXact)和要截断的页面编号(pageno)等。

typedef struct xl_clog_truncate
{
	int			pageno;
	TransactionId oldestXact;
	Oid			oldestXactDb;
} xl_clog_truncate;
  • 使用memcpy函数从WAL记录的数据部分复制截断信息到xlrec变量
  • 更新最旧的事务ID,发生截断操作时,就知道小于或等于这个新最旧事务ID的事务都已经不再需要保留在日志中了
  • 释放xlrec.pageno之后的所有页面

如果info不是CLOG_ZEROPAGE也不是CLOG_TRUNCATE,则记录一个致命错误

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值