当前位置: 首页 > news >正文

PostgreSQL源码分析——pg_basebackup

涉及到的代码主要在src/backend/replication以及bin/pg_basebackup中。

我们知道pg_basebackup是一个进行基础备份的工具,除了使用这个工具,还可以用底层API的方式进行基础备份,主要过程如下:

  1. 连接到数据库
  2. 执行select pg_start_backup('lable')命令。(会强制发生一次checkpoint,并将检查点记录到backup_label文件中)
  3. 执行备份,把数据目录进行复制(包含backup_label)
  4. 执行select pg_stop_backup命令,(删除backup_label文件,并在WAL日志中写入一条XLOG_BACKUP_END的记录,当备节点回放到该记录时,就知道备份结束了,数据达到了一致点,可以对外提供服务了)
  5. 备份过程中产生的WAL日志进行复制

其实,pg_basebackup工具就是对底层API的封装,其主要过程是相同的,但具体到代码,并不是直接调用的pg_start_backup,pg_stop_backup函数,而是通过一些命令的形式,这些特殊的命令定义在src/backend/replication/repl_gram.y中,后面我们会进行分析。

主流程

pg_basebackup执行基础备份的主要流程如下,其中,涉及到libpq协议与服务端进行连接,通信,向服务端发送一些特殊的命令语句,这些命令的解析在src/backend/replication/repl_gram.y中可以查看到具体的语法定义。主流程如下:

main(int argc, char **argv)
--> GetConnection();   // 连接服务端,(例如主节点)--> PQconnectdbParams(keywords, values, true);
--> BaseBackup();      // 执行基础备份--> GenerateRecoveryConfig(conn, replication_slot);   // 用于生成primary_conninfo配置信息--> PQconninfo(pgconn);--> RunIdentifySystem(conn, &sysidentifier, &latesttli, NULL, NULL)basebkp = psprintf("BASE_BACKUP LABEL '%s' %s %s %s %s %s %s %s %s %s",escaped_label,estimatesize ? "PROGRESS" : "",includewal == FETCH_WAL ? "WAL" : "",fastcheckpoint ? "FAST" : "",includewal == NO_WAL ? "" : "NOWAIT",maxrate_clause ? maxrate_clause : "",format == 't' ? "TABLESPACE_MAP" : "",verify_checksums ? "" : "NOVERIFY_CHECKSUMS",manifest_clause ? manifest_clause : "",manifest_checksums_clause);// 向服务端发送执行命令"BASE_BACKUP LABEL 'pg14bak' PROGRESS   NOWAIT    MANIFEST 'yes' "--> PQsendQuery(conn, basebkp)    --> PQgetResult(conn);    // Get the starting WAL location--> StartLogStreamer(xlogstart, starttli, sysidentifier);--> CreateReplicationSlot(param->bgconn, replication_slot, NULL, temp_replication_slot, true, true, false)// 执行命令 "CREATE_REPLICATION_SLOT \"pg_basebackup_2553309\" TEMPORARY PHYSICAL RESERVE_WAL"--> PQexec(conn, query->data);// Start a child process and tell it to start streaming.// 创建一个单独的子进程用于日志传输bgchild = fork();if (bgchild == 0){/* in child process */LogStreamerMain(param);--> ReceiveXlogStream(param->bgconn, &stream)   // Receive a log stream starting at the specified position.}if (!writing_to_stdout && manifest)ReceiveBackupManifest(conn);    // receive backup manifest

整个的过程,最重要的有3点:

  1. 在进行备份前,执行一次checkpoint,记录开始的位置,在服务端接收到BASE_BACKUP LABLE命令后,生成备份标签文件backup_lable,这个文件最重要的作用是记录数据库恢复的起始位置。当启动备份实例时,会读该文件进行恢复。
  2. 复制数据库数据文件
  3. 日志复制

我们可以看一下backup_lable文件中的内容:

postgres@slpc:~/pgsql/pgbak$ ls
backup_label      pg_commit_ts   pg_notify     pg_subtrans  postgresql.auto.conf
backup_manifest   pg_dynshmem    pg_replslot   pg_tblspc    postgresql.conf
base              pg_hba.conf    pg_serial     pg_twophase  standby.signal
current_logfiles  pg_ident.conf  pg_snapshots  PG_VERSION
global            pg_logical     pg_stat       pg_wal
log               pg_multixact   pg_stat_tmp   pg_xact
postgres@slpc:~/pgsql/pgbak$ cat backup_label 
START WAL LOCATION: 0/C000028 (file 00000001000000000000000C)    备份开始时日志的位置
CHECKPOINT LOCATION: 0/C000060                                   检查点的位置
BACKUP METHOD: streamed                                          备份方法
BACKUP FROM: primary                                             备份源    
START TIME: 2023-08-02 17:15:58 CST                              备份开始的物理时间
LABEL: pg14bak                                                   备份标签
START TIMELINE: 1

具体过程

仅看上面的主流程还是有一些不清楚的地方的。

这里有个很重要的命令BASE_BACKUP LABEL,备份命令,获取XLOG的存放路径和备份开始时日志的位置,那么服务端这块是怎么处理的呢?我们看一下服务端的相关代码:

void PostgresMain(int argc, char *argv[], const char *dbname, const char *username)
{// ...if (am_walsender)WalSndSignals();/* Perform initialization specific to a WAL sender process. */if (am_walsender)InitWalSender();for (;;){firstchar = ReadCommand(&input_message);switch (firstchar){case 'Q':			/* simple query */{const char *query_string;/* Set statement_timestamp() */SetCurrentStatementStartTimestamp();query_string = pq_getmsgstring(&input_message);pq_getmsgend(&input_message);if (am_walsender){if (!exec_replication_command(query_string))exec_simple_query(query_string);}elseexec_simple_query(query_string);send_ready_for_query = true;}break;}
}/* Execute an incoming replication command.*/
bool exec_replication_command(const char *cmd_string)
{// .../* Looks like a WalSender command, so parse it. */parse_rc = replication_yyparse();if (parse_rc != 0)ereport(ERROR,(errcode(ERRCODE_SYNTAX_ERROR),errmsg_internal("replication command parser returned %d",parse_rc)));switch (cmd_node->type){case T_IdentifySystemCmd:cmdtag = "IDENTIFY_SYSTEM";set_ps_display(cmdtag);IdentifySystem();EndReplicationCommand(cmdtag);break;case T_BaseBackupCmd:cmdtag = "BASE_BACKUP";set_ps_display(cmdtag);PreventInTransactionBlock(true, cmdtag);SendBaseBackup((BaseBackupCmd *) cmd_node);EndReplicationCommand(cmdtag);break;case T_CreateReplicationSlotCmd:cmdtag = "CREATE_REPLICATION_SLOT";set_ps_display(cmdtag);CreateReplicationSlot((CreateReplicationSlotCmd *) cmd_node);EndReplicationCommand(cmdtag);break;case T_DropReplicationSlotCmd:cmdtag = "DROP_REPLICATION_SLOT";set_ps_display(cmdtag);DropReplicationSlot((DropReplicationSlotCmd *) cmd_node);EndReplicationCommand(cmdtag);break;case T_StartReplicationCmd:{StartReplicationCmd *cmd = (StartReplicationCmd *) cmd_node;cmdtag = "START_REPLICATION";set_ps_display(cmdtag);PreventInTransactionBlock(true, cmdtag);if (cmd->kind == REPLICATION_KIND_PHYSICAL)StartReplication(cmd);elseStartLogicalReplication(cmd);/* dupe, but necessary per libpqrcv_endstreaming */EndReplicationCommand(cmdtag);Assert(xlogreader != NULL);break;}case T_TimeLineHistoryCmd:cmdtag = "TIMELINE_HISTORY";set_ps_display(cmdtag);PreventInTransactionBlock(true, cmdtag);SendTimeLineHistory((TimeLineHistoryCmd *) cmd_node);EndReplicationCommand(cmdtag);break;case T_VariableShowStmt:{DestReceiver *dest = CreateDestReceiver(DestRemoteSimple);VariableShowStmt *n = (VariableShowStmt *) cmd_node;cmdtag = "SHOW";set_ps_display(cmdtag);/* syscache access needs a transaction environment */StartTransactionCommand();GetPGVariable(n->name, dest);CommitTransactionCommand();EndReplicationCommand(cmdtag);}break;default:elog(ERROR, "unrecognized replication command node tag: %u",cmd_node->type);}// ...
}

我们继续看一下SendBaseBackup函数的实现。

/** SendBaseBackup() - send a complete base backup.** The function will put the system into backup mode like pg_start_backup()* does, so that the backup is consistent even though we read directly from* the filesystem, bypassing the buffer cache.*/
void SendBaseBackup(BaseBackupCmd *cmd)
{basebackup_options opt;SessionBackupState status = get_backup_status();if (status == SESSION_BACKUP_NON_EXCLUSIVE)ereport(ERROR,(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),errmsg("a backup is already in progress in this session")));parse_basebackup_options(cmd->options, &opt);WalSndSetState(WALSNDSTATE_BACKUP);if (update_process_title){char		activitymsg[50];snprintf(activitymsg, sizeof(activitymsg), "sending backup \"%s\"",opt.label);set_ps_display(activitymsg);}perform_base_backup(&opt);
}

主流程如下:

SendBaseBackup(BaseBackupCmd *cmd)
--> perform_base_backup(&opt);// creates the necessary starting checkpoint and constructs the backup label file.--> do_pg_start_backup(opt->label, opt->fastcheckpoint, &starttli, labelfile, &tablespaces, tblspc_map_file);--> RequestCheckpoint(CHECKPOINT_FORCE | CHECKPOINT_WAIT | (fast ? CHECKPOINT_IMMEDIATE : 0));--> CreateCheckPoint(flags | CHECKPOINT_IMMEDIATE);

相关文章:

PostgreSQL源码分析——pg_basebackup

涉及到的代码主要在src/backend/replication以及bin/pg_basebackup中。 我们知道pg_basebackup是一个进行基础备份的工具,除了使用这个工具,还可以用底层API的方式进行基础备份,主要过程如下: 连接到数据库执行select pg_start_…...

QT基础 - 常见图表绘制

目录 零. 前言 一. 添加模块 折线图 三. 树状图 四. 饼图 五. 堆叠柱状图 六. 百分比柱状图 七. 散点图和光滑曲线图 散点图 光滑曲线图 零. 前言 Qt Charts 是 Qt 框架的一个模块,用于创建各种类型的图表和数据可视化。它为开发者提供了一套功能强大的工…...

解释React中的“端口(Portals)”是什么,以及如何使用它来渲染子节点到DOM树以外的部分。

React中的“端口(Portals)”是一种将子节点渲染到DOM****树以外的部分的技术。在React应用中,通常情况下组件的渲染是遵循DOM的层次结构,即子组件会渲染在父组件的DOM节点内部。然而,有些情况下,开发者可能…...

java实现分类下拉树,点击时对应搜索---后端逻辑

一直想做分类下拉,然后选择后搜索的页面,正好做项目有了明确的需求,查找后发现el-tree的构件可满足需求,数据要求为:{ id:1, label:name, childer:[……] }形式的,于是乎,开搞! 一…...

【2024最新华为OD-C/D卷试题汇总】[支持在线评测] 披萨大作战(100分) - 三语言AC题解(Python/Java/Cpp)

🍭 大家好这里是清隆学长 ,一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为OD-C/D卷的三语言AC题解 💻 ACM银牌🥈| 多次AK大厂笔试 | 编程一对一辅导 👏 感谢大家的订阅➕ 和 喜欢💗 &#x1f…...

探索Facebook对世界各地文化的影响

随着数字化时代的到来,社交媒体已成为连接世界各地人们的重要平台之一。而在这个领域的巨头之一,Facebook不仅是人们沟通交流的场所,更是一座桥梁,将不同地域、文化的人们联系在一起。本文将探索Facebook对世界各地文化的影响&…...

导出requirements.txt

文章目录 requirements.txt导出环境中所有包导出当前项目的包可能遇到的问题 requirements.txt 在Python项目中,通常使用requirements.txt文件来列出所有需要的第三方库和模块。这个文件通常位于项目的根目录下,并且在安装Python项目时,可以…...

我主编的电子技术实验手册(09)——并联电路

本专栏是笔者主编教材(图0所示)的电子版,依托简易的元器件和仪表安排了30多个实验,主要面向经费不太充足的中高职院校。每个实验都安排了必不可少的【预习知识】,精心设计的【实验步骤】,全面丰富的【思考习…...

数据结构_二叉树

目录 一、树型结构 二、二叉树 2.1 概念 2.2 特殊的二叉树 2.3 二叉树的性质 2.4 二叉树的存储 2.5 遍历二叉树 2.6 操作二叉树 总结 一、树型结构 树是一种非线性的数据结构,它是由 n(n>0) 个有限结点组成一个具有层次关系的集合,一棵 n 个…...

Java线程池七个参数详解

ThreadPoolExecutor 是JDK中的线程池实现,这个类实现了一个线程池需要的各个方法,它提供了任务提交、线程管理、监控等方法 下面是 ThreadPoolExecutor 类的构造方法源码,其他创建线程池的方法最终都会导向这个构造方法,共有7个参…...

产品Web3D交互展示有什么优势?如何快速制作?

智能互联网时代,传统的图片、文字、视频等产品展示方式,因为缺少互动性,很难引起用户的兴趣,已经逐渐失去了宣传优势。 Web3D交互展示技术的出现,让众多品牌和企业找到了新的方向,线上产品展示不在枯燥无趣…...

Python | Leetcode Python题解之第171题Excel列表序号

题目: 题解: class Solution:def titleToNumber(self, columnTitle: str) -> int:number, multiple 0, 1for i in range(len(columnTitle) - 1, -1, -1):k ord(columnTitle[i]) - ord("A") 1number k * multiplemultiple * 26return n…...

【银河麒麟】高可用触发服务器异常重启,处理机制详解

1.服务器环境以及配置 【机型】物理机 处理器: Intel 内存: 126G 【内核版本】 4.19.90-25.16.v2101.ky10.x86_64 【银河麒麟操作系统镜像版本】 Kylin-Server-10-SP2-Release-Shenzhen-Metro-x86-Build01-20220619 Kylin-HA-10-SP2-Release-S…...

性能工具之 JMeter 常用组件介绍(七)

文章目录 一、后置处理器1、Regular Expression Extractor(正则表达式提取器)2、JSON Extractor(JSON表达式提取器)3、Regular Expression Extractor(正则表达式提取器) 二、小结 本文主要介绍JMeter主流后置处理器的功能 一、后置处理器 从上面可以看出后置处理可以插件挺多&a…...

Python学习笔记15:进阶篇(四)文件的读写。

文件操作 学习编程操作中,我觉得文件操作是必不可少的一部分。不管是读书的时候学习的c,c,工作的前学的java,现在学的Python,没学过的php和go,都有文件操作的模块以及库的支持,重要性毫无疑问。…...

角度调制与解调电路

music! (黄佳庆老师可爱捏) 调角 角度调制有较好的抗噪性能。 调相 相位变化的频率变化的微分,频率变化是相位变化的积分 相位的变化率就是频率 调频 调相与调频的关系 大F是输入信号的频率,大Ω是输入信号的角频率 …...

数据分析:微生物组差异丰度方法汇总

欢迎大家关注全网生信学习者系列: WX公zhong号:生信学习者Xiao hong书:生信学习者知hu:生信学习者CDSN:生信学习者2 介绍 微生物数据具有一下的特点,这使得在做差异分析的时候需要考虑到更多的问题&…...

Linux驱动开发(二)--字符设备驱动开发提升 LED驱动开发实验

1、地址映射 在编写驱动之前,需要知道MMU,也就是内存管理单元,在老版本的 Linux 中要求处理器必须有 MMU,但是现在Linux 内核已经支持无 MMU 的处理器了。 MMU的功能如下: 完成虚拟空间到物理空间的映射 内存保护&…...

钡铼BL101网关助力智慧城市路灯远程智能管控

在迈向智慧城市的征途中,基础设施的智能化改造是关键一环,而路灯作为城市脉络的照明灯塔,其智能化升级对于节能减排、提升城市管理效率具有重要意义。钡铼BL101网关,作为Modbus转MQTT的专业桥梁,正以其卓越的性能和广泛…...

如何优雅的使用Github Action服务来将Hexo部署到Github Pages

文章目录 参考文章前提条件1. 初始化Hexo2. 初始化仓库3. 创建Token4. 修改_config.yml5. 配置Github Action工作流6. 推送验证7. 配置Github Pages8. 修改Hexo主题样式10. 添加文章遇到了一些问题和方案1. 网站没有样式问题2. 图片不显示 参考文章 Bilibili视频教程-9分钟零成…...

After Effects 2024 mac/win版:创意视效,梦想起航

After Effects 2024是一款引领视效革命的专业软件,汇聚了创意与技术的精华。作为Adobe推出的全新版本,它以其强大的视频处理和动画创作能力,成为从事设计和视频特技的机构,如电视台、动画制作公司、个人后期制作工作室以及多媒体工…...

信息打点web篇----web后端源码专项收集

前言 欢迎来到我的博客 个人主页:北岭敲键盘的荒漠猫-CSDN博客 专栏描述:因为第一遍过信息收集的时候,没怎么把收集做回事 导致后来在实战中,遭遇资产获取少,可渗透点少的痛苦,如今决定 从头来过,全面全方位…...

ArcGIS批量投影转换的妙用(地理坐标系转换为平面坐标系)

​ 点击下方全系列课程学习 点击学习—>ArcGIS全系列实战视频教程——9个单一课程组合系列直播回放 这次文章我们来介绍一下,如何巧妙用要素数据集来实现要素的批量投影。不需要ArcGIS的模型构建器与解决。 例如,有多个要素要将CGCS_2000地理坐标系投…...

YOLOv10训练自己的数据集(图像目标检测)

目录 1、下载代码 2、环境配置 3、准备数据集 4、yolov10训练 可能会出现报错: 1、下载代码 源码地址:https://github.com/THU-MIG/yolov10 2、环境配置 打开源代码,在Terminal中,使用conda 创建虚拟环境配置 命令如下&a…...

解决不能拉取 docker 镜像

# 编辑镜像仓库文件 sudo vi /etc/docker/daemon.json { "registry-mirrors": ["https://registry.docker-cn.com","https://s3d6l2fh.mirror.aliyuncs.com"] }# 重启docker sudo systemctl restart docker参考 https://blog.csdn.net/u01019733…...

44、基于深度学习的癌症检测(matlab)

1、基于深度学习的癌症检测原理及流程 基于深度学习的癌症检测是利用深度学习算法对医学影像数据进行分析和诊断,以帮助医生准确地检测癌症病变。其原理和流程主要包括以下几个步骤: 数据采集:首先需要收集包括X光片、CT扫描、MRI等医学影像…...

Vue3 【仿 react 的 hook】封装 useTitle

效果预览 页码加载时&#xff0c;自动获取网页标题通过input输入框&#xff0c;可以实时改变网页标题 代码实现 index.vue <template><h1>网页的标题为&#xff1a; {{ titleRef }}</h1><p>通过input输入框实时改变网页的标题 <input v-model"…...

CSS 计数器

CSS 计数器 CSS 计数器是 CSS 中一个强大但经常被忽视的功能。它们允许开发者创建和管理计数器,这些计数器可以在文档中自动递增,非常适合用于编号章节、列表项或其他文档元素。在本文中,我们将深入探讨 CSS 计数器的使用方法、优势和实际应用场景。 CSS 计数器的基本概念…...

磁力搜索器,解读新一代的搜索引擎方式,磁力王、磁力猫等引擎的异同及原理

最近国内几年&#xff0c;不依赖追踪服务器的磁力搜索开始流行&#xff0c;成为新的资源搜索的方式。 我们平常所说的磁力王&#xff08;jigecili.com)、磁力猫(yinghuacili.com)、bt磁力&#xff08;btcili.cn)、磁力狗最新版&#xff08;cilizhai.net)、磁力兔子、磁力宝、人…...

Apache Doris 全新分区策略 Auto Partition 应用场景与功能详解 | Deep Dive系列

编辑&#xff1a;SelectDB 技术团队 在当今数据驱动的时代&#xff0c;如何高效、有序地管理数据库中的海量数据成为挑战。为了处理庞大的数据集&#xff0c;分布式数据库引入了类似分区和分桶策略&#xff0c;通过将数据按特定规则划分成较小的单位并分布到不同节点上&#x…...

用dw做购票网站/百度扫一扫识别图片在线

Hive 将元数据存储在 RDBMS 中&#xff0c;有三种模式可以连接到数据库&#xff1a; 1)ingle User Mode&#xff1a; 此模式连接到一个 In-memory 的数据库 DerbHive 将元数据存储在 RDBMS 中&#xff0c;有三种模式可以连接到数据库&#xff1a;1)ingle User Mode&#xff1a;…...

曰本免费网站/360建站和凡科哪个好

最近更新了我的Wordpress&#xff0c; 发现他的新编辑器不错。与传统编辑器不同&#xff0c;叫块编辑器&#xff0c;所有的页面都是一个个方块构成&#xff0c;很容易编辑中意的页面。这个块编辑器是wordpress 5.0自带的&#xff0c;不需要安装插件。 先把参考或我的学习资料列…...

seo技术推广培训/seo论坛站长交流

C是2015年上半年同比增长最快的编程语言。具体为C 增长3.1%&#xff0c;Java 增长2.0%&#xff0c;C#增长1.6%&#xff0c;Python增长1.6%。C大幅度增长的原因可能是引入了新的C11标准。这使得C被大范围的接受。 C 11标准为C带来了很多新的特性和提升。而且现在 C的工具 GCC &a…...

郑州网站建设选微锐/淘宝怎么优化关键词步骤

“Couldn’t agree a key exchange algorithm”&#xff0c;putty登录服务器或winscp登录服务器报这个错误 如图&#xff0c;登录报错怎么处理&#xff1f; 原因&#xff1a;随着Linux版本的更新&#xff0c;服务器支持的加密算法也在不断更新&#xff0c;而老版本的Putty不支…...

快速建设小说盗版网站/站长工具精华

check 检查 RPM 数据库问题check-update 检查是否有可用的软件包更新clean 删除缓存数据deplist 列出软件包的依赖关系distribution-synchronization 已同步软件包到最新可用版本downgrade 降级软件包erase 从系统中移除一个或多个软件包fs Creates filesystem snapshots, or l…...

做网站设计怎么样/b站推广网站入口2023的推广形式

很多时候,我们都会抱怨,为什么别人就能活的那么潇洒,而自己活的那么累. 有时候,看见别人的成功那只是表面上的,各行各业都没有绝对的天才, 就算有,那也是极少数 多数人都是平庸的 但是成功的人,一定累过的,一定有一段时间是辛苦的,一定有段时间的成长. 在我们抱怨世道不公的时候…...