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

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的研发。

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值