干数据库运维的都知道,备份这事儿平时看不出价值,出事儿那天才知道它有多重要。openGauss这两年国产化落地不少,但它的物理备份方案一直挺折腾人——官方自带的gs_dump只能做逻辑备份,数据量大或者想做到能精确回放事务的恢复,逻辑备份就有点顶不住了。gs_probackup这个从pg_probackup移植适配过来的工具,算是把openGauss的物理备份、增量备份、基于时间点的恢复这些能力补全了。
这篇文章我把gs_probackup做增量备份恢复的完整链路写出来,包括方案选型、环境准备、参数配置、全量+增量备份实操、恢复实操,以及我在真实环境里踩过的坑和排错过程。适合正在用openGauss跑生产、想建立一套正经备份体系的DBA和运维同学。下面这些命令我都实际跑过,照着做基本能复现。
1. 备份方案怎么选:为什么是gs_probackup
1.1 openGauss备份的现状与痛点
openGauss开箱自带的备份手段主要是gs_dump和gs_dumpall,这两个都是逻辑备份,把数据导出成SQL文件或者COPY格式的数据文件。逻辑备份在库比较小、恢复精度要求不高的场景下够用,但生产库一旦到了几百GB甚至上TB,劣势就非常明显:导出慢、恢复慢,更重要的是它只能还原到“某个备份时刻”的数据快照,没办法做到基于时间点恢复(PITR),也没办法按事务ID精确回放。业务误删数据这种事故,逻辑备份基本救不回来。
另一个常见的土办法是直接冷拷贝数据文件。这方案的问题在于要停库才能保证一致性,对于7×24小时的业务来说基本不可接受。手工拷贝还容易漏文件、丢WAL,恢复的时候各种对不上。所以真正要在生产环境解决openGauss的备份问题,必须上物理备份工具。
1.2 gs_probackup的核心能力
gs_probackup是openGauss社区从PostgreSQL生态的pg_probackup移植适配过来的物理备份工具。它做的事本质上就是“把数据文件原样备份下来,配合WAL日志做一致性恢复”,但具体能力比一句话描述的要多得多:
- 全量备份:把整个数据目录完整备份一份,作为后续增量的基础。
- 页级增量备份:基于openGauss的PTRACK机制,只备份自上次备份以来被修改过的数据页。
- WAL归档管理:把WAL日志统一归档,支持恢复到任意时间点和指定事务。
- 备份集校验:可以检查备份链的完整性,确认备份集可恢复。
- 并行备份恢复、压缩、保留策略清理等工程化能力。
这套能力和商业数据库的备份工具已经很接近了,而且它是开源、随openGauss发行版自带的,不需要额外采购商业组件。
1.3 与其他方案的对比
| 方案 | 备份粒度 | PITR | 对业务影响 | 适合场景 |
|---|---|---|---|---|
| gs_dump / gs_dumpall | 逻辑 | 不支持 | 基本无影响 | 小库、迁移、结构导出 |
| 冷拷贝数据目录 | 物理 | 不支持 | 需要停库 | 维护窗口、测试环境 |
| gs_probackup全量 | 物理 | 支持 | 几乎无感知 | 各种规模 |
| gs_probackup页级增量 | 物理 | 支持 | 几乎无感知 | 大库、高频备份 |
结论很直接:生产环境的openGauss,如果对恢复时间、恢复精度有要求,gs_probackup是目前开源方案里最靠谱的选择。我见过不少团队一开始用gs_dump顶着,等库涨到一定程度、备份时间压不住业务窗口的时候,最后还是回到gs_probackup这条路上。
2. 环境准备与初始化配置
2.1 确认工具与安装方式
openGauss的安装包默认会带上gs_probackup,通常在$GAUSSHOME/bin目录下。装完数据库后直接用which gs_probackup确认即可。如果确实没有,可以从openGauss社区的Gitee仓库拉源码自己编译,过程也不复杂:
git clone https://gitee.com/opengauss/gs_probackup.git cd gs_probackup mkdir build && cd build cmake .. -DCMAKE_BUILD_TYPE=Release make -j4 && make install编译完把生成的二进制软链到$GAUSSHOME/bin下,或者加进PATH。然后确认版本:
gs_probackup --version这里有个小提醒:不同openGauss版本自带的gs_probackup版本可能不一样,命令参数有些细微差异。动手之前先跑一遍gs_probackup --help,把-B、-i、-b这几个核心参数的写法确认清楚。
2.2 初始化备份目录并注册实例
gs_probackup需要一个独立的“备份目录”,它所有的备份集、WAL归档都统一放在这里管理。建议把这个目录放在单独的挂载盘上,和数据库数据目录物理隔离,避免互相挤占磁盘。
mkdir -p /data/gauss_backup chown -R omm:dbgrp /data/gauss_backup su - omm gs_probackup init -B /data/gauss_backupinit命令会生成备份目录的基础结构。接下来把要备份的数据库实例注册进去:
gs_probackup add-instance -B /data/gauss_backup -D /data/omm/data -i gauss1参数逐一说清楚:
-B:备份目录,就是刚才建的那个路径。-D:openGauss的数据目录。不确定的话,用show data_directory;在数据库里查一下。-i:实例名,自己起一个,建议和业务或环境对应,比如gauss_prod、gauss_test,后面所有命令都要用这个实例名。
注册完成后,备份目录下会生成backup.control和实例级别的配置文件。可以用gs_probackup show-config -B /data/gauss_backup -i gauss1查看实例当前的配置项。
2.3 数据库侧参数配置
这是最容易踩坑的环节。gs_probackup的物理备份强依赖几个数据库参数,不配好,后面所有备份命令都会报错。打开postgresql.conf(openGauss里通常是postgresql.conf加上postgresql.conf.helper的组合),确认以下参数:
wal_level = hot_standby archive_mode = on archive_command = 'cp %p /data/wal_archive/%f' ptrack_enable = on session_timeout = 0逐个说明:
wal_level:至少要archive级别,openGauss默认通常是hot_standby,一般不用动。archive_mode:必须开on,关了备份直接失败。archive_command:WAL归档命令。上面示例是归档到本地目录,需要先建好/data/wal_archive目录并chown。另一种方式是让gs_probackup自己接管归档,把WAL直接归档进备份目录里,命令形如:
archive_command = 'gs_probackup archive-archive -B /data/gauss_backup -i gauss1 --wal-file-name %f'两种方式各有适用场景。我常用本地目录方式,简单直观,PITR的时候手动把WAL拷到恢复实例即可。如果图省事,推荐用gs_probackup自管理方式,恢复时它会自动从备份目录里找WAL。
ptrack_enable:PTRACK开关,页级增量备份必须开。这个参数openGauss支持reload生效,但我建议和前面几个一起改完重启,统一生效。session_timeout:openGauss的空闲会话超时参数,默认值在不同版本里差异很大。备份期间如果有长事务或者交互操作,很容易被它杀掉,建议直接置0关闭,这个问题下面排错章节还会细讲。
改完参数重启数据库:
gs_ctl restart -D /data/omm/data注意:
archive_mode和wal_level修改后必须重启数据库才生效,reload没用。很多人就是改了参数不重启,然后备份一直报“WAL archiving is not enabled”,排查半天才发现是这回事。
3. 增量备份的运行机制
3.1 两种备份模式的区别
gs_probackup支持两种备份模式,由-b参数指定:
full:全量备份,整个数据目录完整拷贝。后续所有增量都以它为基础。page:页级增量备份,基于PTRACK,只备份自上次备份以来被修改过的数据页。
这里的“增量”和很多数据库工具里的差异增量、累计增量不太一样。page增量是一条链式结构:
全量备份(base) → page增量1(备份自base以来变化的数据页) → page增量2(备份自page增量1以来变化的数据页) → ...
恢复的时候,工具从全量开始,依次应用page增量备份,最后回放WAL日志,得到完整的恢复点。只要链条上任何一个环节损坏或丢失,整条链就废了。
3.2 PTRACK是怎么工作的
PTRACK(Page Tracking)是openGauss提供的数据页跟踪机制。当ptrack_enable=on时,数据库会在内存里记录哪些数据页被修改,周期性地把这份“脏页位图”刷到磁盘上,一般落在数据目录下的ptrack相关目录里。
page增量备份时,gs_probackup读取PTRACK位图文件,找出变化的数据页,只备份这些页。相比全量备份,page增量的数据量通常只有全量的百分之几到十几,备份窗口大幅缩短。我实测一个700GB的库,全量要跑一个多小时(开了压缩),page增量平均只要3到5分钟。
使用PTRACK有三个前提缺一不可:
- 必须有至少一个全量备份作为基础。
ptrack_enable=on。- 系统时钟稳定,别乱跳,时区也别随意改动,PTRACK位图依赖时间戳和LSN的对应关系。
3.3 关键参数与配置项
备份命令里常用的核心参数先列出来:
-B /data/gauss_backup # 备份目录,所有命令都要带 -i gauss1 # 实例名 -b full|page # 备份模式 -p 5432 # openGauss数据库端口 --archive # 备份期间归档WAL --threads N # 并行线程数,建议和CPU核数相关 --compress # 压缩备份数据 --log-level-console # 控制台日志级别实例级的默认配置用set-config统一管理,这样执行备份时不用每次敲一堆重复参数:
gs_probackup set-config -B /data/gauss_backup -i gauss1 \ --compress-algorithm=zlib \ --compress-level=6 \ --archive-timeout=300 \ --retention-redundancy=2 \ --retention-window=14--compress-algorithm/--compress-level:压缩算法和级别,zlib的6级在压缩率和速度之间比较均衡。--archive-timeout:WAL归档超时时间,单位秒,默认就是300。--retention-redundancy:最少保留多少个备份集。--retention-window:保留多少天以内的备份。
这些配置会在执行备份时自动生效,不用每次手动拼参数。
4. 备份实操:从全量到增量
4.1 全量备份实操
第一次做备份必须先跑全量。全量备份的产物是后续所有增量的基础,所以完成后一定要做校验。命令如下:
su - omm gs_probackup backup -B /data/gauss_backup -i gauss1 -b full -p 5432 --archive --threads 4 --compress我一般固定加--compress,生产库普遍比较大,压缩能省不少磁盘空间。--threads根据机器核数来,4线程在大多数环境已经够用,SSD盘可以放到8,机械盘建议别超过4,否则备份期间IO抢占业务。
备份过程会输出进度日志,结束之后用show命令看备份集列表:
gs_probackup show -B /data/gauss_backup -i gauss1输出大概长这样:
Instance: gauss1 BACKUP INFO: ID | Mode | Status | Time | WAL | 大小 ----------|------|--------|----------------------|----------------|---------- ABC123456 | full | OK | 2024-05-20 14:00:00 | 000000010000... | 23 GB看到Status是OK,并且有一行Mode为full的记录,说明全量备份建立成功。
4.2 增量备份实操
全量完成后,日常的增量命令很简单,把模式换成page就行:
gs_probackup backup -B /data/gauss_backup -i gauss1 -b page -p 5432 --archive --threads 4 --compress这个命令会基于最近的全量+page链,把自上次备份以来变化的数据页备份一遍。对大多数业务场景,快的话几秒钟,慢的话几分钟就跑完了。增量备份的价值就在这里——可以做到每小时甚至每半小时备份一次,对生产几乎无感。
有一点要特别注意:page增量备份依赖上一次备份成功完成。如果上一次page增量跑到一半失败了,下一次备份会把这次的失败点当作基准,恢复时就会出问题。所以每次备份完,养成看一眼退出码的习惯,或者把备份日志接到监控告警里。
4.3 备份校验与查看
备份做了不等于一定能恢复。我强烈建议每次备份完成后跑一遍校验:
gs_probackup validate -B /data/gauss_backup -i gauss1这条命令会检查备份链的完整性,包括数据文件块是否有缺失、WAL是否齐全。输出里没有ERROR,才说明这个备份链是可用的。
日常巡检用带-R参数的show查看整个恢复链状态:
gs_probackup show -B /data/gauss_backup -i gauss1 -R-R会展示每个备份和WAL的对应关系,以及当前能恢复到什么位置。这条命令我每次巡检都会跑,一眼就能看出链条有没有断。
4.4 备份调度与保留策略
生产环境的备份不能靠手工点命令。用crontab做定时任务,建议的策略是:
- 数据量不大(几百GB以内):每天凌晨1点全量,每小时page增量。
- 数据量大(TB级):每周日全量,每天凌晨plus每小时page增量。
crontab里这么写:
0 1 * * * /home/omm/scripts/full_backup.sh >> /home/omm/scripts/backup.log 2>&1 0 * * * * /home/omm/scripts/page_backup.sh >> /home/omm/scripts/backup.log 2>&1脚本内容核心就是前面那两条gs_probackup命令,加上日志时间戳。脚本记得用su - omm -c方式执行,别用root跑。
保留策略由set-config里配的retention参数控制,执行备份时会自动清理过期备份。手动清理用:
gs_probackup delete -B /data/gauss_backup -i gauss1 --delete-expired注意:删除备份时要格外小心,别把当前增量链的base全量删掉。如果
--retention-redundancy配得太小,可能出现所有page增量都依赖的全量被清理,整条链失效的惨案。我的经验是redundancy至少配2,也就是保留最近两个全量周期,宁可多占点磁盘,也别让自己无备份可用。
5. 恢复实操:把数据还原出来
5.1 恢复前的准备工作
恢复这件事我只想说一句:先演练,再实战。真要出事了再翻文档,大概率手忙脚乱。下面的过程建议在测试环境完整跑一遍,把命令和步骤刻进肌肉记忆。
恢复前确认几件事:
- 备份目录可访问,
show能看到所有备份集且状态正常。 - WAL归档文件齐全,尤其做PITR的时候。
- 目标数据目录已停止旧实例,或者是个全新空目录。
- 磁盘空间足够,恢复出来的数据加上WAL,通常需要原库1.5倍以上的空间。
恢复的目标目录不要和旧数据目录混用。建议用独立路径,比如/data/omm/data_restore。
5.2 恢复到当前一致点
最简单的场景:把数据恢复到最近一次备份的一致性状态,也就是最近一次成功的page增量备份加上WAL回放到该点。
gs_probackup restore -B /data/gauss_backup -i gauss1 -D /data/omm/data_restore这个命令默认会找最近有效的备份链,把全量加所有page增量还原到目标目录。恢复完成后,检查目标目录文件权限:
chown -R omm:dbgrp /data/omm/data_restore然后用临时端口启动实例,验证数据:
gs_ctl start -D /data/omm/data_restore -p 15432 gsql -d postgres -p 15432 -r正常的话直接查表、查数据、查对象元数据,确认没问题再切业务。注意:恢复出来的实例和原实例在同一个环境里,端口、IP都冲突,启动前先把postgresql.conf里的端口改掉,或者干脆先只做验证,不接入任何应用。
5.3 PITR恢复到指定时间点
这是gs_probackup最值钱的功能。业务误删数据、跑了错误的UPDATE、DROP了表,都可以利用WAL回放到事故之前。
gs_probackup restore -B /data/gauss_backup -i gauss1 -D /data/omm/data_restore \ --recovery-target-time '2024-05-21 03:15:00+08' \ --recovery-target-inclusive=true参数说明:
--recovery-target-time:恢复到哪个时间点,格式带时区。openGauss对+08这种写法兼容比较好,直接用'2024-05-21 03:15:00'多数情况也能识别。--recovery-target-inclusive:是否包含目标时间点那一刻的数据,默认true。
恢复完成后,目标数据目录里会生成recovery.conf或recovery.signal之类的恢复标志文件,数据库启动时自动进入恢复状态,回放WAL到指定目标,然后转为可读写。
openGauss这里有个细节:PITR回放依赖从备份点到目标时间点之间的WAL。如果之前配置的是本地cp归档方式,需要把这些WAL手动拷到恢复实例的pg_xlog(新版本也可能是pg_wal,按实际目录名为准)目录下:
mkdir -p /data/omm/data_restore/pg_xlog cp /data/wal_archive/* /data/omm/data_restore/pg_xlog/如果不拷贝,实例启动后回放到备份点就会停住,恢复的目标时间点根本达不到,而且日志里会一直报找不到WAL文件的错误。
5.4 恢复后的完整性验证
恢复完成后别急着切业务,先做一轮验证:
- 用
gs_ctl start把实例拉起来,观察pg_log下的启动日志,确认没有ERROR。 - 检查关键表的数据量,和业务侧对一下行数。
- 抽样验证最近的数据,比如今天凌晨产生的订单、日志是否都在。
- 检查存储过程和函数是否存在、能否正常执行。PITR恢复会回到历史时间点,之后建立的存储过程、函数自然也不存在,应用接入前要和开发确认一遍。
- 如果恢复了用户和角色,用gsql逐一验证登录权限。
经验之谈:PITR有个很容易被忽略的坑——业务一直在建索引、加字段、改存储过程的话,恢复到老时间点之后,这些结构变更也不存在。这不是备份工具的缺陷,是PITR本身的语义。所以恢复之后通常还要配合一份逻辑导出的元数据来补做结构迁移,这就是为什么我建议生产环境同时保留gs_dump的逻辑备份做补充。
6. 常见问题与排错实录
6.1 WAL归档不生效导致备份失败
报错场景:执行backup --archive时报ERROR: WAL archiving is not enabled。
先确认archive_mode确实是on,注意不是reload,要重启数据库。再确认archive_command有没有语法错误,路径目录是否已创建、属主是否正确。openGauss有些场景下postgresql.conf和postgresql.conf.helper都会参与配置加载,改错位置会被覆盖。修改之后用数据库命令复核:
show archive_mode; show archive_command;看到实际生效的值和你预期一致,再重新跑备份。
6.2 PTRACK报错与处理
page增量备份时报ptrack is not enabled或者找不到ptrack文件,多半是两个原因:一是ptrack_enable没开,二是刚开启后还没来得及生成PTRACK位图文件。
解决办法:开启ptrack_enable后先跑一次全量备份,再跑page增量。第一次page增量会基于全量生成位图,之后才能正常做增量。如果ptrack目录下文件异常,比如磁盘故障导致位图损坏,gs_probackup会报读取失败。不要想着修复位图,重新做一次全量重建基础更省事。
6.3 session unused timeout导致连接中断
如果你用gsql连上去执行\l或跑耗时比较久的操作,终端突然打出这样一串:
WARNING: session unused timeout. FATAL: terminating connection due to session unused timeout说明openGauss的session_timeout参数把空闲会话杀掉了。这个问题在备份和运维场景里尤其讨厌——gs_probackup备份时会在数据库内建立短连接,正常情况下没问题;但如果你在一个交互会话里手动触发备份,或者某些工具连接保持时间太长,就可能被杀掉,备份任务莫名其妙中断。
解决方法:
gs_guc set -D /data/omm/data -c "session_timeout = 0"改完reload或者重启生效。生产环境如果不想全局关掉,也可以只在备份工具的连接层面做配置,但最简单可靠的就是调成0。这个参数直接影响备份和运维操作的稳定性,我建议一律置0。
6.4 恢复后实例无法启动
恢复完了,gs_ctl start报错,常见就几个原因:
- 权限不对,恢复目录属主不是omm。用
chown -R omm:dbgrp解决。 - 目标目录里有旧的postmaster.pid文件残留,或者端口被占用。删除pid文件,换个端口启动。
- recovery.conf配置了不合理的恢复目标,或者恢复目标不可达(WAL缺失),实例会一直处于恢复状态。看日志,缺哪个WAL就去归档目录找。
- postgresql.conf、pg_hba.conf等配置文件和恢复实例不匹配。比如原库配置了很大的shared_buffers,恢复目标机器内存不够,起不来。
排查方法就一句话:看日志。openGauss的日志在数据目录下的pg_log里,启动失败的具体原因都会记在最新的日志文件里,照着解决就完事了。
6.5 磁盘空间与性能问题
备份目录被写满是最容易出事故的。全量加增量加WAL归档,数据膨胀速度可能超预期。我建议:
- 备份目录和数据库目录分开挂载。
- 定期清理过期备份,保留策略配好之后别频繁改。
- 开启压缩,zlib压缩率一般能到2到5倍。
- 监控备份目录使用率,超过80%触发告警。
性能方面,--threads开太高会导致备份期间IO抢占业务。经验值:数据盘是SSD可以开4到8,机械盘建议2到4。备份尽量安排在业务低峰期,定时任务已经是凌晨跑了,就别再叠个全量备份到白天高峰。
| 问题 | 常见原因 | 处理动作 |
|---|---|---|
| WAL archiving is not enabled | archive_mode未生效 | 重启数据库,复核参数 |
| ptrack is not enabled | ptrack_enable关闭 | 开启后先做全量 |
| session unused timeout | session_timeout过小 | 置0并reload |
| 恢复后起不来 | 权限/端口/WAL缺失 | 看pg_log逐项排查 |
| 备份目录写满 | 保留策略未配置 | 压缩+定时清理+告警 |
最后说点我自己的体会。
备份这条链路,工具选型只占一小半,真正决定生死的是日常的验证和演练。gs_probackup用起来并不难,难的是给它配一套可持续运行的体系:定时、监控、保留策略、定期恢复演练,一个都不能少。我见过太多环境装了工具、跑了备份、但从没真正恢复过,等出事了才发现备份集是坏的、WAL不齐、权限不对。
我的建议很简单:每次备份结束自动validate,每个季度在测试环境做一次完整的全量+增量恢复演练,把恢复步骤写成文档、标好责任人。真到了灾难那天,这套动作能让你从容地把数据救回来。另外,恢复演练时多试试PITR,别只恢复最近一致点——真正容易出问题的,恰恰是那个你不太敢碰的时间点回放。