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

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

cxp 2024-09-23
16

海山数据库(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,则记录一个致命错误

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

评论