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

海山数据库(He3DB)源码解读:He3DB-XLogInsert函数

于巍 2024-08-13
79

XLogInsert

函数主体参数

XLogRecPtr XLogInsert(RmgrId rmid, uint8 info) { }
  • RmgrId rmid

    • uint8类型的别名参数。唯一标识触发WAL记录生成的不同资源管理器
      (Resource Manager ID)
  • uint8 info

    • 资源管理器其他额外信息

函数主题流程

XLogRecPtr XLogInsert(RmgrId rmid, uint8 info) { XLogRecPtr EndPos; /* XLogBeginInsert() must have been called. */ if (!begininsert_called) elog(ERROR, "XLogBeginInsert was not called"); /* * The caller can set rmgr bits, XLR_SPECIAL_REL_UPDATE and * XLR_CHECK_CONSISTENCY; the rest are reserved for use by me. */ if ((info & ~(XLR_RMGR_INFO_MASK | XLR_SPECIAL_REL_UPDATE | XLR_CHECK_CONSISTENCY)) != 0) elog(PANIC, "invalid xlog info mask %02X", info); TRACE_POSTGRESQL_WAL_INSERT(rmid, info); /* * In bootstrap mode, we don't actually log anything but XLOG resources; * return a phony record pointer. */ if (IsBootstrapProcessingMode() && rmid != RM_XLOG_ID) { XLogResetInsertion(); EndPos = SizeOfXLogLongPHD; /* start of 1st chkpt record */ return EndPos; } do { XLogRecPtr RedoRecPtr; bool doPageWrites; bool topxid_included = false; XLogRecPtr fpw_lsn; XLogRecData *rdt; int num_fpi = 0; /* * Get values needed to decide whether to do full-page writes. Since * we don't yet have an insertion lock, these could change under us, * but XLogInsertRecord will recheck them once it has a lock. */ GetFullPageWriteInfo(&RedoRecPtr, &doPageWrites); rdt = XLogRecordAssemble(rmid, info, RedoRecPtr, doPageWrites, &fpw_lsn, &num_fpi, &topxid_included); EndPos = XLogInsertRecord(rdt, fpw_lsn, curinsert_flags, num_fpi, topxid_included); } while (EndPos == InvalidXLogRecPtr); XLogResetInsertion(); return EndPos; }
- typedef uint64 XLogRecPtr;
	日志记录位置的64位无符号整数


- elog会写到日志中
	初始值: begininsert_called = false;
	该变量关联到XLogBeginInsert函数

	- 刚开始为false,XLogBeginInsert中将其设为true
	作用:确保一定要走XLogBeginInsert函数
  • 检测info信息中是否包含无效的位,如果有,报PANIC错误,这是最高错误级别,需要立即停止所有操作并重启数据库

  • 追踪记录哪个资源管理器用了WAL的插入,以及该资源管理器其他信息

    • TRACE、LOG_DEBUG与elog的区别

      • TRACE和LOG_DEBUG不会影响数据库运行,用于调试、定位bug;
        elog可能导致数据库停止等操作,比如错误级别为PANIC
  • 如果当前处于bootstrap下且资源管理器ID不等于XLOG的资源管理器

    • 函数宏 定义

        - BootstrapProcessing:表示系统正在执行bootstrap过程,这是创建模板数据库的过程,发生在数据库系统首次初始化时。
        InitProcessing:表示系统正在初始化过程中,但这不是引导过程。这可能是指数据库系统安装或更新后的初始化步骤。
        NormalProcessing:表示系统处于正常处理模式,即数据库正在接受读写请求并正常运行。
      
    • rmid != RM_XLOG_ID

      • 不等于XLOG的资源管理器ID
    • 重置构造的缓冲区

void XLogResetInsertion(void) { int i; for (i = 0; i < max_registered_block_id; i++) registered_buffers[i].in_use = false; num_rdatas = 0; max_registered_block_id = 0; mainrdata_len = 0; mainrdata_last = (XLogRecData *) &mainrdata_head; curinsert_flags = 0; begininsert_called = false; }
	- 解释

		- max_registered_block_id:当前已注册的最大缓冲区ID
		- 已注册的缓冲区信息结构体

	- 该循环,确保已注册的缓冲区都标记为未使用

- 1)SizeOfXLogLongPHD利用MAXALIGN结合页头部数据的大小来对齐大小
2)用EndPos指向这个对齐后大小的开始位置,并返回这个位置EndPos

  • GetFullPageWriteInfo(&RedoRecPtr, &doPageWrites);

    • 获得全页写的信息
  • XLogRecordAssemble函数

    • Xlog记录信息的组装
  • XLogInsertRecord函数

    • 将 rdt 指向的日志记录插入到 WAL 中,并返回 EndPos,该值表示这个日志记录在 WAL 中的结束位置(即下一个日志记录应该开始的位置)。这个结束位置对于后续的日志记录插入和恢复过程都是非常重要的。
  • do while循环不断的将日志插入WAL中,直到返回的EndPos位置为InvalidXLogRecPtr

再次重置缓冲区

并返回日志记录的最终结束位置

作者介绍

薛炬,移动云数据库工程师,负责云原生数据库He3DB的研发。

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

评论