PostgreSQL源码分析——日志归档

PG中有日志归档功能,主要目的就是备份恢复,PITR,为啥要做日志归档呢?因为在做检查点时会清理WAL日志,清理了之后,就没法实现恢复到任意时刻数据库状态了,而有了日志归档,我们可以保存从数据库初始状态到当前时刻的所有日志,相当于给数据库做了一个备份。当发生故障或者误操作时,可以恢复到指定时刻数据库的状态。

打开日志归档

在配置文件中配置archive_mode=on打开日志归档,启动时会创建归档进程archiver,通过archive_command中配置的命令进行归档。

# - Archiving -
archive_mode = on               # enables archiving; off, on, or always (change requires restart)
archive_command = 'cp %p /home/postgres/pgsql/archive/%f'               # command to use to archive a logfile segment
                                # placeholders: %p = path of file to archive
                                #               %f = file name only
                                # e.g. 'test ! -f /mnt/server/archivedir/%f && cp %p /mnt/server/archivedir/%f'
archive_timeout = 1800          # force a logfile segment switch after this
                                # number of seconds; 0 disables
归档进程源码

我们看一下归档进程的源码,在src/backend/postmaster/pgarch.c中:

PgArchiverMain(void)
--> pgarch_MainLoop();	// 进入归档主循环
	--> pgarch_ArchiverCopyLoop(); 
		--> pgarch_readyXlog

日志归档的逻辑,主要是什么时候进行归档?核心要点是发生日志段切换时会触发,那我们看一下那些情况会触发日志切换

  • 当WAL日志中的一个日志段(日志文件)已满,需要切换到下一个日志段时,就可以通知archiver进程将这个日志归档。产生日志切换的进程会在通知Postmaster之前先在pg_wal/archive_status下生成一个.ready文件,这个文件和待归档日志同名。
  • 如果长时间没有归档,触发archive_timeout超时,则强制进行日志切换,强制归档
  • 调用pg_switch_wal()函数手动触发

我们看一下归档进程主循环的实现逻辑,就是等待归档通知信号,拷贝日志:

static void pgarch_MainLoop(void)
{
   
	pg_time_t	last_copy_time = 0;
	bool		time_to_stop;
	// 进入主循环, 等待收到日志归档通知
	do {
   
		ResetLatch(MyLatch);

		/* When we get SIGUSR2, we do one more archive cycle, then exit */
		time_to_stop = ready_to_stop;

		/* Check for barrier events and config update */
		HandlePgArchInterrupts();

		// ...

		/* Do what we're here for */
		pgarch_ArchiverCopyLoop();		// 进行日志归档,拷贝WAL日志
		last_copy_time = time(NULL);

		/* Sleep until a signal is received, or until a poll is forced by
		 * PGARCH_AUTOWAKE_INTERVAL having passed since last_copy_time, or until postmaster dies. */
		if (!time_to_stop)		/* Don't wait during last iteration */
		{
   
			pg_time_t	curtime = (pg_time_t) time(NULL);
			int			timeout;

			timeout = PGARCH_AUTOWAKE_INTERVAL - (curtime - last_copy_time);
			if (timeout > 0) {
   
				int			rc;
				rc = WaitLatch(MyLatch, WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,timeout * 1000L, WAIT_EVENT_ARCHIVER_MAIN);
				if (rc & WL_POSTMASTER_DEATH)
					time_to_stop = true;
			}
		}
	} while (!time_to_stop);
}
触发归档的时机1

其中最重要的就是什么时候发信号,通知可以归档,是在切换日志段的时候,什么时候会切换日志段呢?用户可以通过调用pg_switch_wal函数强制切换日志段,正常情况下是不断插入日志的过程中,如果超出了日志段的大小,会触发切换日志段。我们看一下这块的处理逻辑。

具体的XLogWrite调用过程可参考文章PostgreSQL源码分析——WAL日志(二)

static void XLogWrite(XLogwrtRqst WriteRqst, bool flexible)
{
   
	// ...
			/*
			 * If we just wrote the whole last page of a logfile segment,
			 * fsync the segment immediately.  This avoids having to go back
			 * and re-open prior segments when an fsync request comes along
			 * later. Doing it here ensures that one and only one backend will
			 * perform this fsync.
			 *
			 * This is also the right place to notify the Archiver that the
			 * segment is ready to copy to archival storage, and to update the
			 * timer for archive_timeout, and to signal for a checkpoint if
			 * too many logfile segments have been used since the last checkpoint. */
			if (finishing_seg)	// 一个段已满
			{
   
				// 将该段刷入磁盘,保证归档日志的数据完整性
				issue_xlog_fsync(openLogFile, openLogSegNo);

				// 通知walsender进程发送日志给standby
				/* signal that we need to wakeup walsenders later */
				WalSndWakeupRequest();

				LogwrtResult.Flush = LogwrtResult.Write;	/* end of page */

				if (XLogArchivingActive())
					XLogArchiveNotifySeg(openLogSegNo);	// 发送日志归档通知信息

				// 更新日志切换时间,计算archive_timeout用
				XLogCtl->lastSegSwitchTime = (pg_time_t) time(NULL);
				XLogCtl->lastSegSwitchLSN = LogwrtResult.Flush;

				/*
				 * Request a checkpoint if we've consumed too much xlog since
				 * the last one.  For speed, we first check using the local
				 * copy of RedoRecPtr, which might be out of date; if it looks
				 * like a checkpoint is needed, forcibly update RedoRecPtr and
				 * recheck.
				 */
				if (IsUnderPostmaster && XLogCheckpointNeeded(openLogSegNo))
				{
   
					(void) GetRedoRecPtr();
					if (XLogCheckpointNeeded(openLogSegNo))
						RequestCheckpoint(CHECKPOINT_CAUSE_XLOG);
				}
			}
}


我们看一下这个XLogArchiveNotify函数实现,日志归档通知,创建一个.ready文件,表示可以进行归档。当归档完成时,将对应的.ready文件重命名为.done文件

void XLogArchiveNotifySeg

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/742541.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【研究】AI大模型需要什么样的硬件?

关注AI大模型 x 硬件的两条思路 从22年11月OpenAI推出ChatGPT至今,我们看到Chatbot应用的能力不断增强,从最初的文字问答,迅速向具有自主记忆、推理、规划和执行的全自动能力的AI Agent发展。我们认为端侧智能是大模型发展的重要分支。建议投…

中达新材业绩增长遭问询:资产负债率远高同行,曾被执行1.1亿

《港湾商业观察》廖紫雯 近日,浙江中达新材料股份有限公司(以下简称:中达新材)完成北交所二轮问询,对北交所提出的业绩增长真实性核查、募集资金投资项目必要性等问题做出回复。 本次中达新材拟募集资金5.58亿投入年…

docker容器相关命令

☆ 问题描述 docker容器相关命令 ★ 解决方案 1. 拉取镜像 docker pull ubuntu2.查看镜像是否拉取成功 docker images3. 运行容器 docker run -itd --name <容器名称> -p <主机端口>:<容器端口> --cpus30 ubuntu # -p设置端口 --cpus/-c 设置核心 …

从删库到还原

欢迎来到我的博客&#xff0c;代码的世界里&#xff0c;每一行都是一个故事 &#x1f38f;&#xff1a;你只管努力&#xff0c;剩下的交给时间 &#x1f3e0; &#xff1a;小破站 从删库到还原 魔法一魔法二魔法三魔法四查看是否开启binlog&#xff0c;且format为row执行以下命…

公交行业系统特点及面临的挑战

在当前城市发展中&#xff0c;公交行业作为公共交通的重要组成部分&#xff0c;承担着重要的社会责任。随着科技的进步和城市化进程的加快&#xff0c;公交行业系统也在不断地发展和完善。然而&#xff0c;从目前的发展情况来看&#xff0c;公交行业系统也呈现出一些显著的特点…

pandas将dataframe展开/拉伸成一个series

pandas提供了一个函数实现这个操作&#xff1a; dataframe.stack()示例程序&#xff1a; import pandas as pd import numpy as npdf pd.DataFrame(np.random.randint(0, 10, size(2, 4)), columns[col_1, "col_2", "col_3", "col_4"]) # 展…

【全资料】软件建设过程全资料整理(原件打包)

获取方式&#xff1a;本文末个人名片获取。 工作安排任务书&#xff0c;可行性分析报告&#xff0c;立项申请审批表&#xff0c;产品需求规格说明书&#xff0c;需求调研计划&#xff0c;用户需求调查单&#xff0c;用户需求说明书&#xff0c;概要设计说明书&#xff0c; 技术…

职业技能大赛引领下大数据专业实训教学的改革研究

随着信息化时代的加速发展&#xff0c;大数据专业作为新兴的热门领域&#xff0c;正日益成为高等职业教育体系中不可或缺的一部分&#xff0c;其承担着为社会培养大批具有高素质应用技能的大数据技术人才的重任。职业技能大赛作为检验和提升学生技能水平的有效平台&#xff0c;…

别再盲目生产了!精益KPI管理让你事半功倍!

在竞争日益激烈的制造业领域&#xff0c;如何提升生产效率、降低成本、确保产品质量&#xff0c;是每个企业都需要面对的重要课题。而研华科技作为工业自动化领域的领军企业&#xff0c;凭借其独特的精益生产KPI分析与管理平台&#xff0c;为企业提供了一套行之有效的解决方案。…

高考志愿填报:选择好专业还是好学校?

人不走空 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌赋&#xff1a;斯是陋室&#xff0c;惟吾德馨 高考志愿填报&#xff1a;选择好专业还是好学校&#xff1f; 每年高考结束后&#xff0c;考生和家长面临的一个…

网络设备框架

文章目录 前言一、主要流程二、Linux网络设备驱动架构1.概述2.读入数据 总结 前言 Linux中的Ethernet驱动框架涉及到网络设备驱动程序的多个方面&#xff0c;包括初始化、注册、数据传输以及与物理层&#xff08;PHY&#xff09;的交互。以下是网络设备驱动架构的概述&#xf…

Spring Boot配置Springdoc

刚刚开通了一个公众号&#xff0c;会分享一些技术博客和自己觉得比较好的项目&#xff0c;同时会更新一些自己使用的工具和图书资料&#xff0c;后面会整理一些面试资料进行分享&#xff0c;觉得有兴趣的可以关注一下。 问题描述 之前文章有提到Spring Boot切换到Springdoc&a…

LeetCode刷题之HOT100之乘积最大子数组

2024/6/25 六月也来到了末尾&#xff0c;刷题也刷了一个半月左右。收获还是有的&#xff0c;最起码打字快了哈哈&#xff0c;做题啦&#xff01; 1、题目描述 2、逻辑分析 一眼动态规划。 解题思路 遍历数组时计算当前最大值&#xff0c;不断更新令nowMax 为当前最大值&…

【azure openaiai翻译】翻译功能测试及对比(定价,响应速度,响应限制,翻译质量)

最近在测试翻译质量&#xff0c;用到了azure ai service里的文本翻译&#xff08;简称ai翻译&#xff09;和azure openai 。 告一段落&#xff0c;辅以笔记。这两种将分别从定价&#xff0c;响应速度&#xff0c;响应限制&#xff0c;翻译质量进行讲解。 1.azure openai 对于内…

EthernetIP IO从站设备数据 转opc ua项目案例

1 案例说明 设置网关采集EthernetIP IO设备数据把采集的数据转成opc ua协议转发给其他系统。 2 VFBOX网关工作原理 VFBOX网关是协议转换网关&#xff0c;是把一种协议转换成另外一种协议。网关可以采集西门子&#xff0c;欧姆龙&#xff0c;三菱&#xff0c;AB PLC&#xff0…

2005年下半年软件设计师【上午题】试题及答案

文章目录 2005年下半年软件设计师上午题--试题2005年下半年软件设计师上午题--答案 2005年下半年软件设计师上午题–试题 2005年下半年软件设计师上午题–答案

ModbusRTU协议报文解析

ModbusRTU协议报文解析 报文格式&#xff1a; 设备地址/从站地址&#xff1a; 1个字节 指定目标设备地址&#xff08;从站地址&#xff09; 功能码&#xff1a;1个字节 功能码在modbus协议用于表示信息帧的功能&#xff0c;例如读取线圈状态、读取寄存器等。 数据&#xff…

C语言数据结构-分析期末选择题考点(一)

昔我往矣&#xff0c;杨柳依依 今我来思&#xff0c;雨雪霏霏 契子✨ 有道是&#xff1a;得选择题者得天下。临近考试&#xff0c;便总结一下数据结构选择题的常考题型吧&#xff0c;以及预测一下考点&#xff0c;一来是为了备考&#xff0c;二来可以水文。祝各位老铁 “挂柯南…

韩顺平0基础学java——第30天

p600-611 坦克大战&#xff01; 艰难推进中 坦克大战-子弹 发射子弹 1.当发射一颗子弹后&#xff0c;就相当于启动一个线程 2.玩家拥有子弹对象&#xff0c;当按下J时&#xff0c;就启动发射行为&#xff08;线程&#xff09;&#xff0c;让子弹不停移动&#xff0c;形成…

(上位机APP开发)调用华为云命令API接口给设备下发命令

一、功能说明 通过调用华为云IOT提供的命令下发API接口,实现下面界面上相同的功能。调用API接口给设备下发命令。 二、JavaScript代码 function sendUnlockCommand() {var requestUrl = "https://9bcf4cfd30.st1.iotda-app.cn-north-4.myhuaweicloud.com:443/v5/iot/60…