Skip to content

pg_basebackup ​

pg_basebackup 是 PostgreSQL 官方提供的、用于获取基础备份(base backup)的客户端工具。它通过复制协议(replication protocol)连接到一个正在运行的主库或备库,向服务端请求一次完整的基础备份,并把结果写到本地目录(或服务端目录,或直接丢弃)。

它最大的价值在于「省心」:备份开始时自动进入备份模式、结束时自动退出、自动处理备份期间产生的 WAL、自动生成 backup_manifest 校验清单。你不需要手工调用 pg_backup_start() / pg_backup_stop(),也不用担心「文件扫描时刻」与「WAL 起点」是否配套——这些都是工具在协议层替你保证的。

代价是它有一些使用前提(需要 REPLICATION 权限、需要 pg_hba.conf 放行复制连接、需要足够的 walsender),以及它永远只能做集簇级备份、不能选择性备份单库单表。本页按「连接 → 格式 → WAL → 压缩 → 槽 → 表空间 → 进度 → 校验 → 增量 → 性能」的顺序,把它的全部关键选项讲清楚。

前置知识

建议先阅读:物理备份原理、WAL 与检查点

基础概念 ​

pg_basebackup 是什么 ​

pg_basebackup 是一个普通的 PostgreSQL 客户端程序,它使用复制协议(而不是 SQL)与服务端通信:

  • 连接时在启动参数里带上 replication=true,让后端进入 walsender 模式;
  • 通过复制命令(如 BASE_BACKUP)请求服务端开始一次基础备份;
  • 服务端自行执行「开始备份 → 传输文件 → 结束备份」的全过程;
  • 客户端把收到的文件写到目标目录(或 tar 包、stdout)。

因此,备份的一致性由服务端保证,客户端只负责传输与落盘。

使用前提 ​

前提说明
连接用户需具备 REPLICATION 属性或超级用户身份
pg_hba.conf必须放行该用户的复制连接
max_wal_senders至少留出一个 walsender 给备份,使用 -X stream 时还要再多一个
wal_level需为 replica 或更高(logical)
目标目录-D 指定的目录可以不存在(会自动创建),但若存在则必须为空
bash
# 创建一个专用备份用户(最小权限:仅 REPLICATION)
psql -c "CREATE ROLE backup_user WITH LOGIN REPLICATION PASSWORD 'strong_password';"
text
# pg_hba.conf 中放行复制连接
host    replication     backup_user     10.0.0.0/24     scram-sha-256

核心选项速览 ​

选项作用
-D / --pgdata目标目录(tar 格式可写 - 表示 stdout)
-F / --format输出格式:p / plain(默认)、t / tar
-X / --wal-methodWAL 收集方式:n / none、f / fetch、s / stream(默认)
-Z / --compress压缩:[{client|server}-]method[:detail]
-z / --gzip等价于客户端 gzip 压缩(仅 tar 格式)
-c / --checkpoint检查点模式:fast / spread(默认)
-R / --write-recovery-conf生成 standby.signal 并写入连接配置
-C / --create-slot备份前创建 --slot 指定的复制槽
-S / --slot备份时使用指定复制槽
-l / --label备份标签(写入 backup_label)
-T / --tablespace-mapping重定位表空间的落地路径
--waldir指定 WAL 落盘目录(仅 plain 格式)
-P / --progress打印进度
-r / --max-rate限制数据传输速率
-i / --incremental增量备份(PG17+),需提供参考备份的 manifest

输出格式:plain 与 tar ​

格式-F 取值产物特点
平铺文件p / plain与源数据目录相同布局的目录树默认;可直接启动、可增量、可用 --tablespace-mapping
tar 归档t / tarbase.tar(+ 各表空间 OID 命名的 tar、pg_wal.tar)便于打包传输;-D - 可管道输出

WAL 收集方式 ​

方式-X 取值何时获取 WAL关键约束
不含n / none不获取恢复必须依赖外部 WAL 归档
结束时收集f / fetch备份结束后一次性拉取需 wal_keep_size 足够大,否则 WAL 可能已被回收
流式获取s / stream备份期间并行接收默认;需额外一个 walsender

-X stream 是默认值,也是三者在「可靠性」上最优的选择:WAL 从备份一开始就持续接收,不留任何窗口。

-X none 与归档的关系

-X none 产出的备份不含 WAL,它只有在「你另有连续的 WAL 归档」时才可恢复。若既没有归档、又选了 none,这个备份不完整。

backup_manifest ​

除 --no-manifest 外,pg_basebackup 默认会生成 backup_manifest:一份列出备份内所有文件(路径、大小、修改时间、校验和)的 JSON 清单,并放在备份根目录(tar 格式下位于 base.tar 内)。

它是 pg_verifybackup 校验备份的依据,也是 PG17 原生增量备份的基础——增量备份必须引用一份「参考备份的 manifest」。

语法与用法 ​

基本语法 ​

text
pg_basebackup [选项...]

最简用法 ​

bash
# plain 格式 + 流式 WAL + 进度
pg_basebackup -h 127.0.0.1 -p 5432 -U backup_user \
  -D /backup/base_20260930 -Fp -Xs -P
text
    0/2290400 kB (0%), 0/1 tablespace (...)
   600260/1200520 kB (50%), 0/1 tablespace (...)
  1200520/1200520 kB (100%), 0/1 tablespace (...)

tar 格式 + 压缩 ​

bash
# tar 格式,客户端 gzip,写到一个目录
pg_basebackup -h 127.0.0.1 -U backup_user \
  -D /backup/base_tar -Ft -Xs -z -P

直出 stdout(仅 tar 格式) ​

bash
# tar 到 stdout,管道给压缩程序(要求无额外表空间且不使用 WAL 流)
pg_basebackup -h 127.0.0.1 -U backup_user \
  -D - -Ft -Xn | gzip > /backup/base_20260930.tar.gz

校验备份 ​

bash
pg_verifybackup /backup/base_20260930
text
backup successfully verified

详细说明 ​

连接参数与权限 ​

pg_basebackup 复用 libpq 的连接参数,同时支持命令行选项与连接字符串:

选项含义
-h / --host主机名或 socket 目录
-p / --port端口
-U / --username连接用户
-d / --dbname连接字符串或数据库名(可携带完整参数)
-w / --no-password不提示密码
-W / --password强制提示密码
-s / --status-interval向源服务器发送状态包的间隔秒数
bash
# 用连接字符串携带全部参数
pg_basebackup \
  -d "host=10.0.0.11 port=5432 user=backup_user dbname=postgres" \
  -D /backup/base_20260930 -Fp -Xs -P

权限方面有两点必须确认:

sql
-- 1) 用户是否有 REPLICATION 属性
SELECT rolname, rolreplication, rolsuper
FROM pg_roles WHERE rolname = 'backup_user';
text
   rolname   | rolreplication | rolsuper
-------------+----------------+----------
 backup_user | t              | f
(1 row)
sql
-- 2) max_wal_senders 是否留有余量
SELECT name, setting FROM pg_settings WHERE name = 'max_wal_senders';
text
      name       | setting
-----------------+---------
 max_wal_senders | 10
(1 row)

复制连接走的是 replication 伪数据库

复制连接不落在某个具体数据库上,pg_hba.conf 里的 replication 关键字(或 all)必须匹配到。只放行了普通 host 规则而没有放行 host replication,pg_basebackup 会直接报连接被拒绝。

输出格式:plain 与 tar ​

plain 格式(-Fp,默认)产出的目录布局与源数据目录一致:

text
/backup/base_20260930/
├── PG_VERSION
├── base/
├── global/
├── pg_control
├── pg_wal/            # 若使用 -X stream/fetch,含所需 WAL 段
├── backup_label       # 备份标签
├── backup_manifest    # 校验清单
├── tablespace_map     # 若有额外表空间
└── postgresql.auto.conf  # 若使用 -R

当集簇有额外表空间时,plain 格式会把主数据目录放进目标目录,而其他表空间仍按源服务器上的绝对路径落地——这意味着目标机器上必须有对应的目录结构。要改变这一点用 -T(见下文)。

tar 格式(-Ft)把主数据目录打包为 base.tar,每个额外表空间打包为以该表空间 OID 命名的 tar 文件;配合 -X stream/fetch 时 WAL 单独打包为 pg_wal.tar。

bash
# 查看 tar 格式的产物
ls -lh /backup/base_tar/
text
-rw-r--r--  1 postgres postgres  182M Sep 30 02:12 base.tar
-rw-r--r--  1 postgres postgres  6.4M Sep 30 02:12 pg_wal.tar
-rw-r--r--  1 postgres postgres   12M Sep 30 02:12 16385.tar

-D - 只在 tar 格式下可用,且要求「集簇没有额外表空间」并且「不使用 WAL 流」(即必须显式指定 -Xn 或 -Xf)。

WAL 收集方式:-X ​

三种方式的行为差异,直接影响恢复时是否还需要归档:

bash
# 1) stream:备份期间并行接收 WAL(默认,最可靠)
pg_basebackup -D /backup/base_stream -Fp -Xs -P

# 2) fetch:备份结束后一次性拉取所需 WAL
pg_basebackup -D /backup/base_fetch -Fp -Xf -P

# 3) none:不收集 WAL,完全依赖外部归档
pg_basebackup -D /backup/base_none -Fp -Xn -P

-X fetch 的隐患是「时间窗口」:WAL 在备份结束时才被请求,如果备份耗时长而 wal_keep_size 不够,备份起点所需的 WAL 段可能已经被回收,备份直接失败:

conf
# fetch 模式下的必要配置(示例值,需按备份时长与写入量估算)
wal_keep_size = 2GB

-X stream 需要额外的 walsender 与网络带宽,但换来的是「无窗口」。此外 -X stream 有一个附加特性:它顺带把备份期间的 WAL 一并写进备份包,使得备份成为完全独立可启动的(standalone)。

-Xstream 与 --target 不能同时使用

--target=server:/path 表示备份由服务端自行落盘,而 WAL 流式接收是客户端实现的功能,二者矛盾。使用 --target 时必须改写 -Xfetch 或 -Xnone。

压缩:-z 与 -Z ​

-z 是 -Z 的简化形式(仅 tar 格式 + 客户端 gzip)。完整的 -Z 语法为:

text
-Z [{client|server}-]method[:detail]
--compress=[{client|server}-]method[:detail]
部分取值说明
执行位置client / server省略时默认 client;使用 --target 时只有 server 有意义
方法gzip / lz4 / zstd / none也可写整数(0 表示不压缩,>0 表示 gzip 及等级)
细节整数等级,或 level= / workers= 等关键字方法写成整数时不能再带 detail
bash
# 服务端 zstd 压缩(省带宽,耗服务端 CPU)
pg_basebackup -D /backup/base_s -Fp -Xs --compress=server-zstd:level=3

# 客户端 lz4 压缩(快、压缩率一般)
pg_basebackup -D /backup/base_c -Fp -Xs --compress=client-lz4

# tar 格式 + 客户端 zstd:文件名自动加 .zst 后缀
pg_basebackup -D /backup/base_t -Ft -Xs -Z zstd:3

压缩与 WAL 的交互有一条容易踩的规则:使用 -X stream 时,服务端压缩不会作用于 WAL;若使用客户端 gzip 压缩,pg_wal.tar 也会被 gzip 压缩,而其他压缩算法或服务端压缩下 pg_wal.tar 不压缩。要压缩 WAL 中的内容,应改用客户端压缩或 -X fetch。

plain 格式的压缩

plain 格式下不能用客户端压缩(文件需要直接落地),但可以请求服务端压缩:服务端压缩后传输,客户端接收时解压并落盘。

检查点模式:-c fast 与 spread ​

备份开始前,服务端必须做一次检查点。-c 控制这次检查点的行为:

取值行为适用场景
spread(默认)尽量摊薄检查点的 I/O 冲击,尽快完成但不过度影响在线业务绝大多数在线业务场景
fast立即强制完成检查点停机窗口、对备份启动时延敏感的场景
bash
# 在线备份:保持默认
pg_basebackup -D /backup/base_online -Fp -Xs

# 停机窗口:加速检查点
pg_basebackup -D /backup/base_window -Fp -Xs -c fast

fast 会一次性把累积的脏页全部刷盘,产生明显的写 I/O 尖峰;spread 让 I/O 更平滑,代价是备份的「启动时间」稍长。

复制槽与 -C / -S / --no-slot ​

使用复制槽的好处是:服务端会为这个槽保留备份所需的 WAL,避免因 wal_keep_size 不足导致 -X fetch 失败。

bash
# 备份前创建槽,并在备份中使用它
pg_basebackup -D /backup/base_slot -Fp -Xf \
  -S basebackup_slot -C -P

# 已存在槽时直接使用(若用 -C 且槽已存在会报错)
pg_basebackup -D /backup/base_slot2 -Fp -Xf \
  -S basebackup_slot -P

相关选项:

选项作用
-S slotname / --slot指定要使用的复制槽
-C / --create-slot备份前创建该槽(已存在则报错)
--no-slot不使用槽(默认行为,与 -S 互斥)

槽会被 postgresql.auto.conf 记录下来(配合 -R 时),便于后续流复制复用同一份设置。

用槽之后要记得清理

使用 -C 创建的临时槽,如果备份结束后不再需要,应在主库上删除,否则它会持续保留 WAL,长期占用磁盘:

sql
SELECT pg_drop_replication_slot('basebackup_slot');

表空间处理:-T 与 --waldir ​

-T olddir=newdir 把源服务器上位于 olddir 的表空间重定位到接收端的 newdir:

bash
pg_basebackup -D /backup/base_reloc -Fp -Xs \
  -T /data/tblspc/reporting=/backup/tblspc/reporting \
  -T /data/tblspc/archive=/backup/tblspc/archive \
  -P

要点:

  • olddir 必须与源服务器上表空间的定义逐字一致(若源上不存在该路径,不算错误);
  • newdir 不必预先存在,若存在必须为空;
  • 两个路径都必须是绝对路径;路径中含 = 时用反斜杠转义;
  • 可重复指定多个 -T;
  • 重定位后,主数据目录内的符号链接会被更新指向新位置;
  • 只对 plain 格式有效,tar 格式下会被忽略。

--waldir 用于把 WAL 写到别处(默认写进目标目录下的 pg_wal):

bash
pg_basebackup -D /backup/base_wal -Fp -Xs \
  --waldir=/backup/base_wal/wal -P

它要求绝对路径、目标必须为空,且仅 plain 格式可用。

直接生成备库配置:-R ​

-R(--write-recovery-conf)会在目标目录(tar 格式下写入 base.tar)里:

  1. 创建一个 standby.signal 文件;
  2. 把连接设置追加到 postgresql.auto.conf。
bash
pg_basebackup -h 10.0.0.11 -p 5432 -U backup_user \
  -D /var/lib/postgresql/18/main \
  -Fp -Xs -R -P
conf
# postgresql.auto.conf 中被追加的内容(示意)
primary_conninfo = 'user=backup_user passfile=''/var/lib/postgresql/.pgpass'' channel_binding=prefer host=10.0.0.11 port=5432 sslmode=prefer sslcompression=0 sslcertmode=allow sslsni=1 ssl_min_protocol_version=TLSv1.2 gssencmode=prefer krbsrvname=postgres gssdelegation=0 target_session_attrs=any load_balance_hosts=disable'

若同时用 -S 指定了槽,槽名也会被记录进去。这样备份产物就是「拿来即用的备库目录」,只需补上 pg_hba.conf 等无关恢复的配置即可启动。

恢复目录也要清空

用 -R 恢复到已有实例的数据目录时,目标必须为空(与 -D 的规则一致)。若原有数据目录非空,先改名挪走,避免工具报错或产生混合内容。

进度观察与状态上报 ​

客户端侧用 -P 打印进度;服务端侧可以查 pg_stat_progress_basebackup:

sql
SELECT
    pid,
    phase,
    backup_total,
    backup_streamed,
    tablespaces_total,
    tablespaces_streamed
FROM pg_stat_progress_basebackup;
text
  pid  |          phase           | backup_total | backup_streamed | tablespaces_total | tablespaces_streamed
-------+--------------------------+--------------+-----------------+-------------------+----------------------
 21483 | streaming database files |      1200520 |          600260 |                 1 |                    0
(1 row)

phase 的典型取值依次为:initializing → waiting for checkpoint to finish → estimating backup size → streaming database files → transferring wal files。

相关选项:

选项作用
-P / --progress客户端打印进度(近似值,可能不到 100%)
-s / --status-interval状态上报间隔(秒);0 表示禁用周期性上报
--no-estimate-size不做体积预估,backup_total 恒为 NULL
-v / --verbose输出更多细节
bash
# 关闭体积预估:避免在超大库上多花一次全目录扫描
pg_basebackup -D /backup/base_big -Fp -Xs -P --no-estimate-size

当备份包内含 WAL 时,总量无法事先精确估算,进度百分比可能超过 100% 或提前「到 100%」。

清单与校验:manifest 相关选项 ​

选项作用
--no-manifest不生成 backup_manifest
--manifest-checksums=method指定 manifest 中的校验算法(如 NONE、CRC32C、SHA224、SHA256、SHA384、SHA512)
--no-verify-checksums不校验服务端计算的文件校验和(只在 archive_mode 关闭等特殊情形下使用)
bash
# 生成 SHA256 校验的 manifest
pg_basebackup -D /backup/base_sha -Fp -Xs \
  --manifest-checksums=SHA256 -P

# 备份后校验
pg_verifybackup /backup/base_sha

校验清单的价值在「备份成功 ≠ 备份可用」这个老问题上:文件写出来了不代表没被截断或损坏。pg_verifybackup 会比对文件列表、重算校验和,并用 pg_waldump 解析备份携带的 WAL。

bash
# 若备份未携带 WAL,跳过 WAL 解析
pg_verifybackup --no-parse-wal /backup/base_sha

# 若 manifest 不完整(例如从备库备份),可跳过校验和检查
pg_verifybackup --skip-checksums /backup/base_sha

--no-manifest 的代价

不生成 manifest 会让备份无法被 pg_verifybackup 校验,也会让这个备份无法作为 PG17 增量备份的参考备份。除非有明确的特殊理由,不要关闭 manifest。

增量备份:-i(PostgreSQL 17+) ​

PostgreSQL 17 为物理备份引入了原生增量备份。pg_basebackup -i old_manifest_file 会用「上一次备份的 manifest」作为参考,让服务端只传输自那次备份以来被修改的块:

bash
# 1) 先做一次全量备份(会生成 backup_manifest)
pg_basebackup -D /backup/full_20260930 -Fp -Xs -P

# 2) 做增量备份:引用全量备份的 manifest
pg_basebackup -D /backup/incr_20261001 -Fp -Xs -P \
  -i /backup/full_20260930/backup_manifest

关键限制:

  • 增量备份不能直接使用,必须先与它所依赖的备份合并;
  • 合并用 pg_combinebackup:
bash
# 把全量 + 增量合并成一份完整备份
pg_combinebackup /backup/full_20260930 /backup/incr_20261001 \
  -o /backup/combined_20261001
  • 合并后的产物才是可恢复的完整备份;也可以把多个增量一起传入 pg_combinebackup 按顺序合并。
bash
# 全量 + 两个增量合并
pg_combinebackup /backup/full_20260930 \
                 /backup/incr_20261001 \
                 /backup/incr_20261002 \
                 -o /backup/combined_20261002

它的意义在于:全量备份体积大、耗时长,而日常数据变化通常只占一小部分;增量备份只传变化块,能显著降低每日备份的时长与带宽。第三方工具(pgBackRest / Barman)多年来提供的正是这类能力,PG17 把它做进了核心。

性能与限速 ​

pg_basebackup 是重 I/O 操作,对源库的影响来自三处:起始检查点的刷盘、全目录的顺序读取、以及 WAL 流式传输(-X stream)。

选项作用
-r / --max-rate限制从服务端读取数据的速率(单位 KB/s,可用 M 后缀表示 MB/s,范围 32KB/s ~ 1024MB/s)
-N / --no-sync不等待文件安全落盘就返回(更快,但系统崩溃可能导致备份损坏,生产不推荐)
--sync-method落盘方式:fsync(默认)或 syncfs
-n / --no-clean出错时不清理已创建的目录(便于调试)
--compress压缩传输,降低带宽占用、增加 CPU 开销
bash
# 限制速率为 200MB/s,避免挤占在线业务 I/O
pg_basebackup -D /backup/base_limited -Fp -Xs -P -r 200M
bash
# 用 syncfs 减少 fsync 调用次数(适合大目录、现代文件系统)
pg_basebackup -D /backup/base_syncfs -Fp -Xs --sync-method=syncfs

不要在生产使用 -N

-N(--no-sync)让工具不等待文件落盘就返回。此时若操作系统崩溃,备份可能处于不一致状态。它只适合测试。

从备库做基础备份 ​

pg_basebackup 也能从备库取备份,这对降低主库压力非常有价值:

bash
pg_basebackup -h 10.0.0.12 -p 5432 -U backup_user \
  -D /backup/base_from_standby -Fp -Xs -P

备库备份的限制需要在设计时考虑到:

  • 备份中不会生成备份历史文件;
  • 备份结束时无法强制备库切换 WAL 段;使用 -X none 且主库写入很低时,可能长时间等待最后一个段被切换归档,此时可在主库上执行 pg_switch_wal() 主动触发;
  • 若备库在备份期间被提升为主库,备份会失败;
  • 主库必须开启 full_page_writes,保证备份所需 WAL 记录包含完整页镜像。

同时,备库侧要允许复制连接(max_wal_senders、hot_standby、pg_hba.conf)——备库本身也是「会接受复制连接的服务端」。

实战示例 ​

示例一:生产环境标准备份脚本 ​

bash
#!/usr/bin/env bash
set -euo pipefail

BACKUP_ROOT=/backup
STAMP=$(date +%F_%H%M)
TARGET="${BACKUP_ROOT}/full_${STAMP}"

mkdir -p "${TARGET}"

pg_basebackup \
  -h 127.0.0.1 -p 5432 -U backup_user \
  -D "${TARGET}" \
  -Fp -Xs -P -c spread \
  -l "full_${STAMP}" \
  --compress=server-zstd:level=3 \
  --manifest-checksums=SHA256

# 立即校验,失败则以非 0 退出
pg_verifybackup "${TARGET}"

echo "backup ok: ${TARGET}"
text
    0/2290400 kB (0%), 0/1 tablespace (...)
  1200520/1200520 kB (100%), 0/1 tablespace (...)
backup successfully verified
backup ok: /backup/full_2026-09-30_0200

示例二:从备库备份并带复制槽 ​

bash
# 从备库取备份,使用复制槽保证 WAL 不被提前回收
pg_basebackup \
  -h 10.0.0.12 -p 5432 -U backup_user \
  -D /backup/from_standby_20260930 \
  -Fp -Xf -P \
  -S standby_backup_slot -C
bash
# 备份结束后在主库/备库上清理临时槽
psql -h 10.0.0.12 -U postgres \
  -c "SELECT pg_drop_replication_slot('standby_backup_slot');"

示例三:带表空间重定位的备份 ​

bash
# 先把源库的表空间列出来
psql -Atc "SELECT spcname, pg_tablespace_location(oid) FROM pg_tablespace WHERE spcname NOT IN ('pg_default','pg_global');"
text
reporting|/data/tblspc/reporting
archive|/data/tblspc/archive
bash
# 备份时把两个表空间重定位到备份盘
pg_basebackup -h 127.0.0.1 -U backup_user \
  -D /backup/reloc_20260930 -Fp -Xs -P \
  -T /data/tblspc/reporting=/backup/reloc_20260930/tblspc/reporting \
  -T /data/tblspc/archive=/backup/reloc_20260930/tblspc/archive
bash
# 确认 targets 落到了新位置
cat /backup/reloc_20260930/tablespace_map
text
16385 /backup/reloc_20260930/tblspc/reporting
16386 /backup/reloc_20260930/tblspc/archive

示例四:一键生成备库目录 ​

bash
# 直接把备份写成可启动的备库目录
pg_basebackup -h 10.0.0.11 -p 5432 -U replicator \
  -D /var/lib/postgresql/18/main \
  -Fp -Xs -R -P \
  -S standby1_slot -C
bash
# 查看生成的信号文件与自动配置
ls /var/lib/postgresql/18/main/standby.signal
grep -n 'primary_conninfo' /var/lib/postgresql/18/main/postgresql.auto.conf
text
/var/lib/postgresql/18/main/standby.signal
5:primary_conninfo = 'user=replicator host=10.0.0.11 port=5432'
bash
# 启动并确认处于恢复状态
pg_ctl -D /var/lib/postgresql/18/main start
psql -c "SELECT pg_is_in_recovery();"
text
 pg_is_in_recovery
-------------------
 t
(1 row)

示例五:tar 格式备份 + 全量校验 + 归档 ​

bash
# 1) tar 备份,客户端 zstd 压缩
pg_basebackup -h 127.0.0.1 -U backup_user \
  -D /backup/tarpkg_20260930 -Ft -Xs -Z zstd:3 -P
text
    0/2290400 kB (0%), 0/1 tablespace (...)
  1200520/1200520 kB (100%), 0/1 tablespace (...)
bash
# 2) 打包校验:先把 base.tar 解开再校验
mkdir -p /tmp/verify_tar
tar -C /tmp/verify_tar -xf /backup/tarpkg_20260930/base.tar
pg_verifybackup /tmp/verify_tar
text
backup successfully verified
bash
# 3) 归档到异地
rsync -a --delete /backup/tarpkg_20260930/ backup-host:/archive/pg/tarpkg_20260930/

示例六:PG17 增量备份与合并 ​

bash
# 周日:全量
pg_basebackup -D /backup/full_20260928 -Fp -Xs -P

# 周一:增量,引用周日的 manifest
pg_basebackup -D /backup/incr_20260929 -Fp -Xs -P \
  -i /backup/full_20260928/backup_manifest

# 周二:增量,引用周一的 manifest
pg_basebackup -D /backup/incr_20260930 -Fp -Xs -P \
  -i /backup/incr_20260929/backup_manifest
bash
# 需要恢复时,先合并成完整备份
pg_combinebackup /backup/full_20260928 \
                 /backup/incr_20260929 \
                 /backup/incr_20260930 \
                 -o /backup/combined_20260930

# 校验合并结果
pg_verifybackup /backup/combined_20260930
text
backup successfully verified

对比一下体积差异:

bash
du -sh /backup/full_20260928 /backup/incr_20260929 /backup/incr_20260930 /backup/combined_20260930
text
1.2G	/backup/full_20260928
 96M	/backup/incr_20260929
104M	/backup/incr_20260930
1.2G	/backup/combined_20260930

注意事项 ​

-D 目录必须为空。 目标目录不存在时会自动创建;存在且非空则直接报错。不要把它指向一个正在运行的实例的数据目录。

备份不是「可启动的数据库」的代名词。 只有配合了 -X stream/fetch 或外部连续 WAL 归档,备份才具备完整的恢复能力;-X none 的备份需要归档才能用。

-X fetch 依赖 wal_keep_size 足够大。 备份耗时长、写入量大的库,务必调大 wal_keep_size,或改用复制槽、-X stream。

tar 格式下 -T 会被忽略。 表空间重定位只在 plain 格式生效。如果必须要重定位,就不要用 tar。

-D - 有限制。 只有在 tar 格式、无额外表空间、且不用 WAL 流(必须显式 -Xn 或 -Xf)时才允许把备份写到 stdout。

增量备份不能单独恢复。 必须用 pg_combinebackup 与其依赖的全量(以及中间增量)合并,产物才是完整备份。链条中任何一环丢失,增量都用不了。

-N(--no-sync)不要用于生产。 它不等待落盘,系统崩溃可能导致备份文件损坏。

使用 -C 创建的槽要清理。 忘记删除的槽会持续保留 WAL,最终可能撑满磁盘。

从备库备份有其特性。 无备份历史文件、无法强制切换 WAL 段、备库被提升会让备份失败;主库必须开 full_page_writes。

并发备份要谨慎。 官方建议同一时间只做一次备份,然后复制结果——多个 pg_basebackup 并发会同时压榨源库的 I/O 与 walsender 资源。

备份不能替代归档。 pg_basebackup 只解决「起点」问题,恢复时间点的能力来自持续的 WAL 归档。两者必须配套。

最佳实践 ​

  1. 把 -P 与校验做成标准动作。 每次备份都显示进度,并在备份结束后立刻用 pg_verifybackup 校验;校验失败立即告警,不要让坏备份进入保留周期:
bash
pg_basebackup -D /backup/full_$(date +%F) -Fp -Xs -P \
  && pg_verifybackup /backup/full_$(date +%F)
  1. 默认使用 -X stream。 它是默认值,也是唯一没有「WAL 已被回收」时间窗口的方式。只有在明确知道有归档兜底或存储受限时,才考虑 -Xf / -Xn。

  2. 统一使用摊薄式检查点。 在线业务保持 -c spread(默认),只在停机窗口或对备份启动时延敏感时才用 -c fast。

  3. 对备份进程限速。 生产库上用 -r 限制读取速率,避免备份挤占在线业务的 I/O 带宽:

bash
pg_basebackup -D /backup/full_latest -Fp -Xs -P -r 150M
  1. 大库把备份放在备库上执行。 用 -h <standby> 从备库取备份,避免主库承担文件读取开销;同时注意备库备份不生成备份历史文件、且主库需开 full_page_writes。

  2. 需要 WAL 保底时使用复制槽。 通过 -S slot -C 让服务端为备份保留 WAL,避免 -X fetch 因 wal_keep_size 不足而失败;备份后及时 pg_drop_replication_slot() 清理。

  3. 为备份的 manifest 指定强校验算法。 用 --manifest-checksums=SHA256 代替默认的低成本校验,让 pg_verifybackup 更有说服力;不要随意关闭 manifest。

  4. 用 -R 直接产出备库目录。 新建备库时用 -R 一次性生成 standby.signal 与 primary_conninfo,减少手工配置出错:

bash
pg_basebackup -h 10.0.0.11 -U replicator -D /var/lib/postgresql/18/main \
  -Fp -Xs -R -P -S standby1_slot -C
  1. 表空间在备份时就重定位到干净的路径。 用 plain 格式配合 -T,让备份产物自带正确的 tablespace_map,恢复时不必再手工修补路径。

  2. 大库/高频备份考虑 PG17 原生增量。 全量 + 多个增量可以显著缩短每日备份窗口、降低带宽占用;但必须保证整条链(全量 + 全部中间增量)都完整保存,并在需要时用 pg_combinebackup 合并。

  3. 备份命名规范且不可覆盖。 目录名带日期与类型(full_20260930_0200),不要复用固定目录名,避免「写了一半」的目录被误当成完整备份。

  4. 把备份产物同步到独立存储。 备份落在与数据库不同的机器/机房,才具备灾难恢复意义;用 rsync/对象存储网关定期外送,并校验传输完整性。

参考链接 ​