Skip to content

增量备份(pgBackRest / Barman) ​

pg_basebackup 解决的是「怎么拿到一份一致的完整备份」。但在生产环境里,每天都做一次全量备份往往是不现实的:TB 级数据库的全量备份要占用数小时的时间窗口、数倍于数据量的存储空间,以及对源库持续的 I/O 压力。真正可行的策略是「全量 + 增量」——每周(或每天)做一次全量,其余时间只备份「自上次备份以来发生变化的部分」。

增量备份的实现有两条完全不同的技术路线。第一条是 PostgreSQL 原生路线:PG17 引入了原生的块级增量备份能力,服务端通过 WAL 摘要(WAL summarization) 判断哪些数据块被修改过,客户端用 pg_basebackup --incremental 只拉取变更块,恢复前再用 pg_combinebackup 把「全量 + 一串增量」合并成完整备份。这条路线无需第三方软件,但功能相对朴素,没有保留策略、没有并行、没有加密、没有异地仓库管理。

第二条是 第三方备份工具路线:pgBackRest 与 Barman 是这个领域最主流的两个开源方案。它们把「备份链管理、保留策略(retention)、并行压缩、加密、远程仓库、WAL 归档、PITR 编排、监控与校验」打包成一整套流程,是生产环境的事实标准。其中 pgBackRest 采用自研的增量机制(文件级 / v2.46 起的块级增量),Barman 则区分「file-level 增量(rsync)」与「block-level 增量(基于 PG17 原生能力)」。

本页先讲清三种「增量」的语义差异与备份链概念,再分别展开 pgBackRest 与 Barman 的配置模型、备份类型、保留策略、增量机制与恢复方式。所有命令与配置项均来自两个工具的官方文档。

前置知识

建议先阅读:pg_basebackup、物理备份原理

基础概念 ​

为什么需要增量备份 ​

全量备份的成本随数据量线性增长。一个 2TB 的集簇,即使备份速度为 300MB/s,一次全量也要约两小时;如果每天做一次,保留 30 天,光备份存储就需要数十 TB。而业务数据的日均变更量可能只有几 GB——全量备份中 99% 的字节是重复的。

增量备份的价值就在于消除这些重复:

目标增量备份如何实现
缩短备份窗口只传输变更部分,备份耗时从「小时级」降到「分钟级」
降低存储占用一份全量 + 若干增量,总量远小于 N 份全量
提高备份频率备份变轻之后,可以从「每天一次」提高到「每小时一次」,缩小 RPO
降低源库压力读取的数据量更少,对在线业务 I/O 的挤占更小

代价是复杂度上升:增量备份不再是「自包含」的,它依赖一条备份链。链上任何一环损坏或丢失,链尾的增量就不可用。因此使用增量备份,本质上是在用「恢复复杂度」换「备份成本」。

三种「增量」的语义差异 ​

中文里都叫「增量」,但 Full / Differential / Incremental 三者的含义有严格区别。pgBackRest 官方文档给出的定义最清晰:

类型英文备份内容恢复依赖
全量Full Backup整个集簇的全部文件自包含,不依赖任何其他备份
差异Differential Backup自上一次全量以来发生变化的文件依赖那一次全量
增量Incremental Backup自上一次任意类型备份以来变化的文件依赖上一次备份,以及它背后整条链

关键区别在「参照点」:

  • Differential(差异) 的参照点永远是最近一次 Full。周一全量、周二差异、周三差异——周三的差异备份只包含「周一以来」的变化,周三这次不包含周二那次的内容。
  • Incremental(增量) 的参照点是上一次备份(可以是全量、差异或另一个增量)。周一全量、周二增量、周三增量——周三的增量只包含「周二以来」的变化,体积最小。

用一张时间线看差异:

text
周一 Full ──┬── 周二 Diff(相对于周一)
            └── 周三 Diff(相对于周一,不是相对于周二)

周一 Full ──┬── 周二 Incr(相对于周一)
            └── 周三 Incr(相对于周二)

因此:

  • 恢复差异备份:只需要「最近一次差异 + 它对应的全量」,共 2 份。
  • 恢复增量备份:需要「全量 + 从全量到目标之间的全部增量」,可能有很多份。

差异备份 = 更大的体积、更短的恢复链;增量备份 = 更小的体积、更长的恢复链。 实践中常见的组合是「每周全量 + 每天差异 + 每小时增量」,用差异备份在恢复链长度和存储占用之间取得平衡。

备份链与依赖关系 ​

引入增量之后,「一个备份」不再是独立文件,而是链上的一个节点:

text
Full_20260927 ──→ Incr_20260928 ──→ Incr_20260929 ──→ Incr_20260930
     │                 │                 │                 │
   必须存在          依赖前者          依赖前者          依赖前者

由此产生几条铁律:

  1. 删除链中间的备份会让链尾全部失效。 删掉 Incr_20260928,那么 Incr_20260929 与 Incr_20260930 都无法恢复。
  2. 保留策略必须「从链尾往回删」,且不能删成断链。 这就是为什么 pgBackRest 的保留策略以 Full / Diff 为单位计数,而不是以任意备份为单位。
  3. 恢复时必须从链头(Full)开始。 工具会自动解析依赖,但前提是链上每个节点都还在、都通过校验。

PG17 原生增量备份的机制 ​

PG17 的原生增量备份不比较文件修改时间,而是比较数据块。它的判断依据是 WAL 摘要(WAL summarization):

  • 当 summarize_wal = on 时,服务端会在后台生成 WAL 摘要文件,记录「WAL 中各个区段(区间)实际修改了哪些数据块」;
  • 做增量备份时,服务端根据「参考备份对应的 manifest 中记录的 LSN」到「本次备份起始 LSN」之间的 WAL 摘要,推导出需要备份的块;
  • 客户端 pg_basebackup -i <old_manifest> 只拉取这些块;
  • 由于增量备份只包含「部分块」,它不能直接启动,必须先由 pg_combinebackup 与依赖的完整备份合并,产出 synthetic full backup(合成全量备份)。

要点:

事实说明
summarize_wal 必须开启未启用 WAL 摘要时无法执行增量备份
开启位置只能在配置文件中设置(不是 ALTER SYSTEM 之外的普通参数),主库或备库均可
参考物一份参考备份的 backup_manifest 文件
合并工具pg_combinebackup,参数为从最旧到最新的全部备份目录
合并产物synthetic full backup,可再作为后续增量备份的输入

增量备份与 WAL 归档是两回事

原生增量备份解决的是「基础备份怎么变小」,不解决「如何恢复到某个历史时刻」。PITR 依然需要连续的 WAL 归档;增量备份只是让「起点」的获取成本更低。两者必须同时配置。

pgBackRest 与 Barman 的定位差异 ​

维度pgBackRestBarman
定位备份/恢复工具(含 WAL 归档与 PITR 编排)备份管理器(backup manager,更强的灾备编排)
增量机制文件级增量;v2.46 起支持块级增量(block incremental)file-level(rsync);block-level(依赖 PG17 原生能力)
备份类型Full / Diff / Incr 三级Full + 两种 Incremental(无独立 Diff 概念)
配置模型配置文件 + stanza配置文件 + server(按服务器名组织)
元数据仓库内的备份信息通过 barman check / show-backup 等命令查询
云对象存储原生支持 S3 / Azure / GCS,且支持 SFTP通过 barman-cloud-* 系列工具支持
强项性能(并行 + 块级增量)、压缩、加密、增量体积小可观测性、保留策略编排、异地冗余、灾备流程

两者不是互斥的:有些团队用 Barman 做灾备编排,用 pgBackRest 做高效备份。选型时优先看「恢复链的可管理性」与「团队已有运维习惯」,而不是单看备份速度。

关键术语表 ​

术语出处含义
stanza(节)pgBackRest一个 PostgreSQL 集簇的备份配置单元,定义了「数据在哪、备份到哪、怎么归档」
repository(仓库)pgBackRest存放备份与 WAL 归档的位置,可以是本地目录、专用仓库主机或对象存储
retention(保留策略)两者规定保留多少份全量/差异备份,超出的自动过期(expire)
backup chain(备份链)两者一个全量及其派生出的全部增量/差异备份
file-level incrementalBarman基于 rsync(+硬链接)的文件级增量,自包含
block-level incrementalBarman / PG17基于 pg_basebackup 与 WAL 摘要的块级增量,依赖备份链
--typepgBackRestbackup 命令的备份类型:full / diff / incr
backup_methodBarman备份方式:rsync 或 postgres(流式)

语法与用法 ​

原生路线:pg_basebackup + pg_combinebackup ​

bash
# 0) 服务端必须先开启 WAL 摘要(写入 postgresql.conf 后重启/重载)
#    summarize_wal = on

# 1) 周日:全量(产生 backup_manifest,作为后续增量的参考)
pg_basebackup -D /backup/full_20260928 -Fp -Xs -P

# 2) 周一:块级增量,参考全量的 manifest
pg_basebackup -D /backup/incr_20260929 -Fp -Xs -P \
  -i /backup/full_20260928/backup_manifest

# 3) 需要恢复时:按「从最旧到最新」的顺序合并
pg_combinebackup /backup/full_20260928 \
                 /backup/incr_20260929 \
                 -o /backup/combined_20260929

pgBackRest:命令行基本形态 ​

text
pgbackrest [options] [command]
bash
# 创建 stanza、检查配置、执行三种类型的备份
pgbackrest --stanza=demo stanza-create
pgbackrest --stanza=demo check
pgbackrest --stanza=demo --type=full backup
pgbackrest --stanza=demo --type=diff backup
pgbackrest --stanza=demo --type=incr backup

# 查看备份信息、按保留策略清理过期备份
pgbackrest --stanza=demo info
pgbackrest --stanza=demo expire

Barman:命令行基本形态 ​

text
barman backup [OPTIONS] SERVER_NAME
barman restore [OPTIONS] SERVER_NAME BACKUP_ID DESTINATION_PATH
bash
# 全量备份、查看备份、校验配置
barman backup pg
barman list-backups pg
barman show-backup pg latest
barman check pg

详细说明 ​

pgBackRest 的配置模型:配置文件与 stanza ​

pgBackRest 的默认配置文件是 /etc/pgbackrest/pgbackrest.conf,配置格式是「类 INI」的:

  • 段落(section)用方括号表示,如 [global]、[demo];
  • 键值对形如 key=value;
  • 以 # 开头的行是注释;
  • 不支持行尾注释,也不支持引号,键与值两端的空白会被去掉;
  • 同名段落出现多次时会合并。

[global] 段放全局设置(仓库路径、保留策略、加密、日志级别等),其余段落名就是 stanza 名,用于标识「哪个集簇」。

ini
[global]
repo1-path=/var/lib/pgbackrest
repo1-retention-full=2
repo1-retention-diff=7
repo1-cipher-type=aes-256-cbc
compress-type=zstd
process-max=4
log-level-console=info

[demo]
pg1-path=/var/lib/postgresql/18/demo
pg1-socket-path=/var/run/postgresql

关于 stanza 命名,官方文档给了一条很实用的建议:不要用 main / prod 这类「本机集簇名」,而要用描述用途的名字(如 app、dw)。因为同一个 stanza 名会同时用于主库和所有副本,用功能名可以避免「主备切换后配置指向错乱」。

pg1-path 必须与 PostgreSQL 实际报告的 data_directory 完全一致,否则备份会直接报错——这是 pgBackRest 的强校验之一。原因也很直接:恢复场景下数据库进程可能不可用,pgBackRest 无法向 PostgreSQL 询问路径,只能依赖配置。

配置的加载方式有几种(官方文档列出的组合):

text
默认(不传任何选项)        → 加载默认配置文件 + 默认 include 目录下的 *.conf
--config=<文件>            → 只加载指定文件(必须存在)
--config-include-path=<目录> → 加载该目录下全部 *.conf
--config-path=<目录>       → 覆盖默认配置文件与 include 目录的基础路径

pgBackRest 的三级备份与备份链 ​

pgBackRest 的 backup 命令通过 --type 指定备份类型,取值 full / diff / incr,缺省即 incr。这是一个容易踩坑的默认值:只敲 pgbackrest backup 不会做全量。

三种类型的行为:

bash
# 全量:整个集簇,第一个备份必须是 full
pgbackrest --stanza=demo --type=full backup

# 差异:自上一次 full 以来变化的文件
pgbackrest --stanza=demo --type=diff backup

# 增量:自上一次任意类型备份以来变化的文件(默认)
pgbackrest --stanza=demo --type=incr backup

依赖关系(官方文档明确说明):

  • Full 是自包含的,总是可以直接恢复,不依赖 full 之外的任何文件;
  • Diff 恢复时需要「该 diff + 它对应的上一次 full」都有效;
  • Incr 恢复时需要「该 incr + 它之前所有 incr + 之前的 diff(若有)+ 之前的 full」全部有效;如果不存在 diff,则需要「该 incr 之前所有 incr + full」全部有效。

用 info 可以看到备份链与其依赖是否完整:

bash
pgbackrest --stanza=demo info
text
stanza: demo
    status: ok
    cipher: aes-256-cbc

    db (current)
        wal archive min/max (18): 000000010000000000000002/00000001000000000000000F

        full backup: 20260927-020011F
            ...
        diff backup: 20260929-020014D
            ...
        incr backup: 20260930-020017I
            ...

备份标识形如 20260927-020011F:时间戳 + 类型后缀(F = full、D = diff、I = incr)。info 命令也可以用 --set=<备份标识> 查看单个备份的详细信息,或用 --output=json 得到便于监控解析的 JSON。

info 的 status: ok 依赖仓库中的元数据,不需要连接(甚至不需要启动)PostgreSQL——这正是「恢复场景下配置必须自包含」的设计动机。

pgBackRest 的保留策略 ​

保留策略决定「保留多少份备份」,由 expire 命令执行(backup 命令也会在完成后自动触发过期处理)。

配置项含义
repo1-retention-full保留多少份 full 备份
repo1-retention-diff保留多少份 diff 备份
repo1-retention-archive-type归档保留的计数依据:full / diff / incr
repo1-retention-archive保留多少个「按上项计数」的备份所对应的 WAL 归档
ini
[global]
repo1-retention-full=2
repo1-retention-diff=7
repo1-retention-archive-type=full
repo1-retention-archive=2

两条关键规则:

  1. 删除以「链」为单位。 保留策略不会被满足到「把链删断」——如果删掉某个 full 会让某个增量失去依赖,pgBackRest 不会这样删。
  2. WAL 归档的保留与备份保留绑定。 repo1-retention-archive 控制「保留多少个备份所覆盖的 WAL」,设置不当会导致 PITR 时 WAL 已被清理。

手工触发过期(也可用 --dry-run 预览):

bash
pgbackrest --stanza=demo expire
pgbackrest --stanza=demo --dry-run expire

pgBackRest 的压缩、加密与并行 ​

压缩由 compress-type 控制,它同时影响备份与 WAL 归档的压缩方式:

ini
[global]
compress-type=zstd
compress-level=3

加密在客户端完成(即使仓库本身是 S3 等支持服务端加密的对象存储,pgBackRest 也坚持客户端加密):

配置项取值说明
repo1-cipher-typenone(默认)、aes-256-cbc仓库加密算法

启用加密后需要提供口令(通常通过 repo1-cipher-pass 或环境变量提供),口令丢失意味着备份永久不可读,务必纳入密钥管理。

并行由 process-max 控制,它决定同时运行的压缩/传输进程数:

ini
[global]
process-max=4

其他与性能/可靠性相关的常用项:

配置项作用
buffer-sizeI/O 缓冲大小,默认 1MiB,允许 16KiB ~ 16MiB
start-fast备份开始时立即强制一次检查点,让备份尽快启动
backup-standby允许从备库执行备份,减轻主库压力
spool-path异步归档时暂存 WAL 的目录
log-level-console控制台日志级别:off/error/warn/info/detail/debug/trace

start-fast 与 Barman 的 immediate_checkpoint 是同一个思路:用一次「立即检查点」换取更短的备份启动延迟,代价是把检查点的 I/O 一次性压到磁盘上。对在线业务敏感的库要谨慎开启。

pgBackRest 的 Block Incremental(v2.46+) ​

pgBackRest 传统的增量是文件级的:判断一个数据文件是否变化,变化了就整文件拷贝。对于一张大表,即使只改了一行,该文件也会被整份传输。这在 VLDB 场景下依然低效。

v2.46(2023-05-22)引入了 Block Incremental Backup:不再以文件为单位,而是存储发生变化的数据块。它必须与 file bundling 配合使用:

配置项引入版本作用
repo1-bundlev2.39把多个小文件打包存储,减少仓库中的文件数量
repo1-blockv2.46块级增量:只存储变化的块,而非整个文件
ini
[global]
repo1-path=/var/lib/pgbackrest
repo1-bundle=y
repo1-block=y

功能定位的差异(对比传统文件级增量):

text
文件级增量:文件 A(1GB)改了 1 行 → 备份整个文件 A(1GB)
块级增量  :文件 A(1GB)改了 1 行 → 备份变更的少数几个 8KB 块

与 PG17 原生块级增量的关系

pgBackRest 的 block incremental 是自己实现的机制(基于仓库侧的块存储),不以 PG17 的 WAL 摘要为前提。它解决的是「仓库中重复块过多」的问题,可以与任意版本的 PostgreSQL 配合(受 pgBackRest 自身版本约束)。而 PG17 原生增量是「服务端识别变更块、客户端只拉变更块」,二者机制不同、可以叠加。

Barman 的架构与配置 ​

Barman(Backup and Recovery Manager)的定位比 pgBackRest 更偏「备份管理」。它的模型是:一个 Barman 服务器,管理多个被备份的 PostgreSQL 服务器,每台 PostgreSQL 服务器在配置中有一个条目。

配置文件通常是 /etc/barman.conf(或 /etc/barman/barman.conf,再通过 barman.conf.d 分片):

conf
[barman]
barman_user = barman
barman_home = /var/lib/barman
barman_lock_directory = /var/run/barman
log_file = /var/log/barman/barman.log
compression = gzip

[pg]
description = "Primary PostgreSQL server"
ssh_command = ssh postgres@pg
conninfo = host=pg user=barman dbname=postgres

backup_method = postgres
backup_compression = zstd
backup_compression_format = tar

几条实务规则:

  • barman_lock_directory 必须放在本地文件系统上(不要放 NFS)。
  • 若把备份放在 NFS 上:至少使用 NFSv4,并采用 hard,sync 挂载。
  • PG15 起不再支持 exclusive 备份,唯一方式是 concurrent backup;若 backup_options 未设置,Barman 会自动设为 concurrent_backup。
  • 备份启动前 WAL 必须已正确归档到 Barman(通过 archiver 或 streaming_archiver),否则备份会失败。

带宽与压缩相关的配置项:

配置项适用方法说明
bandwidth_limitrsync 与 postgres最大速率(KB/s),默认 0 表示不限速
tablespace_bandwidth_limit仅 rsync按表空间分别限速,格式 tbname:bwlimit[,...]
network_compression不适用于 postgres是否压缩网络传输
backup_compression仅 postgres备份压缩算法:gzip / lz4 / zstd / none
backup_compression_formatpostgresplain(解压后落盘)或 tar(压缩包,默认)
backup_compression_locationpostgresserver 或 client:压缩在哪一侧执行
backup_compression_workerspostgres + zstd压缩线程数(默认 0)
immediate_checkpoint两者是否立即执行检查点(默认 false)

压缩备份的恢复前提

若使用 backup_compression,必须同时设置 staging_path 与 staging_location,否则压缩备份无法恢复。这是 Barman 文档明确要求的配套关系。

Barman 的 file-level 增量(rsync + reuse_backup) ​

Barman 的 file-level incremental 基于 rsync 与硬链接,因此要求操作系统与备份所在文件系统都支持这两者。其核心思想是:后续备份中未变化的文件直接复用上一份备份的文件(硬链接),从而既省空间又省时间。

开关是 reuse_backup(全局或按服务器):

取值行为
off标准全量备份(默认)
link复用上一份备份,未变化文件建硬链接(省空间也省时间)
copy复用上一份备份,未变化文件做拷贝(省时间但不省空间)
conf
[pg]
backup_method = rsync
ssh_command = ssh postgres@pg
reuse_backup = link

也可以在命令行临时覆盖:

bash
barman backup --reuse-backup=link pg

file-level 增量的一个重要特性:它是自包含的。硬链接去重意味着「删除被复用的备份」不会破坏其他备份的完整性——共享的文件会保留到最后一个引用它的备份也被删除为止。因此不需要因为删除某份备份而重新做全量。

另外,对「第一次备份」设 reuse_backup = link 或 copy 没有任何效果:没有可链接/可复制的既有文件,它仍然是一次全量。

Barman 的 block-level 增量(PG17) ​

Barman 从 3.11 开始支持 block-level incremental backup,它建立在 PG17 的原生增量能力之上。与 file-level 的关键差异:

维度file-levelblock-level
传输层rsync over SSHpg_basebackup 流式连接
前置要求无(除文件系统支持硬链接)PG17+、summarize_wal 已开启、backup_method=postgres
去重粒度文件数据页(块)
是否自包含是(硬链接)否(依赖备份链)
压缩支持视 rsync 传输而定目前不支持压缩备份
需要的配置reuse_backup--incremental + 父备份 ID

配置前提:

conf
[pg]
backup_method = postgres

命令形式为「--incremental + 一个父备份标识」:

text
barman backup --incremental BACKUP_ID SERVER_NAME

父备份可以是 full 或另一个 incremental;也可以用 last-full / latest-full 这类快捷方式引用「最近一次符合条件的全量备份」。

两种增量互不兼容

Barman 文档明确:不同类型的增量备份不能混用。你不能在 rsync 备份之上做 block-level 增量,也不能在 pg_basebackup 创建的流式备份之上做 file-level 增量。另外,block-level 增量目前不支持压缩备份。切换增量类型时,必须先做一次对应的全量。

还有两条易被忽略的约束:

  • 若在两次 block-level 增量之间开启了 data_checksums,建议重新做一次全量备份——校验和配置不一致可能在恢复时出问题。
  • summarize_wal 必须在最初那份全量备份之前就已启用,否则后续增量无法进行。

Barman 的恢复:restore 与 delta-restore ​

新版 Barman 的恢复命令是:

text
barman restore [OPTIONS] SERVER_NAME BACKUP_ID DESTINATION_PATH

早期的文档与脚本中使用的是 barman recover,它在较新版本中作为 barman restore 的别名继续可用——如果你的自动化脚本里还有 barman recover,建议统一迁移到 restore 以避免混淆。

BACKUP_ID 可以写具体备份标识,也可以用 auto 让 Barman 自行选择「满足恢复条件的最合适备份」:

bash
# 恢复到目标目录
barman restore pg latest /var/lib/postgresql/18/main

# 由 Barman 自动选择备份
barman restore pg auto /var/lib/postgresql/18/main

delta-restore(增量恢复) 是一个大幅缩短恢复时间的特性:如果目标目录里已经有一份「接近目标状态」的数据(例如崩溃后的原数据目录,或已恢复到一半的目录),Barman 只回填差异部分,而不是整份重写。

配置/选项说明
recovery_options='delta-restore'在配置中全局/按服务器启用
--delta-restore / --no-delta-restore命令行开关
recovery_options=get-wal,delta-restore多个恢复选项用逗号组合

delta-restore 的适用限制

delta-restore 只支持本地 plain 格式备份的恢复,或者 staging_location=local 时的远程恢复。如果你想利用它加速恢复,就不要把备份做成 tar 压缩包(那样必须先解压到 staging,再恢复)。

Barman 的云端与异地能力 ​

Barman 把「对象存储上的备份」拆成一组独立工具(barman-cloud-*),它们可以脱离 Barman 服务器单独运行:

工具作用
barman-cloud-backup把备份上传到对象存储
barman-cloud-restore从对象存储恢复备份
barman-cloud-wal-archive把 WAL 归档到对象存储
barman-cloud-wal-restore从对象存储取回 WAL
barman-cloud-backup-list列出云端备份
barman-cloud-backup-show查看某个云端备份的详情
barman-cloud-backup-keep把某个云端备份标记为「不可自动删除」
barman-cloud-backup-delete删除云端备份
barman-cloud-check-wal-archive检查 WAL 归档状态

配合 WAL 归档使用的还有 barman-wal-archive 与 barman-wal-restore(来自 barman-cli 包)——它们把 WAL 归档/取回封装成可以直接写进 archive_command / restore_command 的单条命令。

「本地备份 + 对象存储副本」的组合(Barman 文档称之为 geographical redundancy,地理冗余)能在机房级故障时保住备份:本地用于快速恢复,云端用于灾难兜底。

备份加密与密钥管理 ​

两个工具都支持客户端加密,且都把「口令/密钥」交给运维侧的密钥管理:

  • pgBackRest:repo1-cipher-type=aes-256-cbc,客户端加密,需要提供口令(repo1-cipher-pass 或环境变量);
  • Barman:encryption=gpg(目前仅 gpg 与 none),依赖 gpg 2.1+ 与预先准备好的密钥对,用 encryption_key_id 指定公钥 ID。

加密口令丢失 = 备份永久不可用

加密是客户端行为,服务端与备份工具都无法帮你解密。把加密口令纳入密钥管理系统(KMS / 密码管理器 / 保险柜流程),并确保恢复演练时使用与生产相同的口令来源。切勿把口令明文写在配置文件里、或随备份一起拷贝。

实战示例 ​

示例一:pgBackRest 从零到第一次全量 ​

bash
# 1) 准备目录
sudo mkdir -p /var/lib/pgbackrest /var/log/pgbackrest
sudo chown postgres:postgres /var/lib/pgbackrest /var/log/pgbackrest
ini
# /etc/pgbackrest/pgbackrest.conf
[global]
repo1-path=/var/lib/pgbackrest
repo1-retention-full=2
process-max=4

[demo]
pg1-path=/var/lib/postgresql/18/demo
bash
# 2) 创建 stanza
sudo -u postgres pgbackrest --stanza=demo stanza-create

# 3) 检查配置(会验证 pg1-path、归档设置、仓库可写等)
sudo -u postgres pgbackrest --stanza=demo check

# 4) 第一次备份:必须是 full
sudo -u postgres pgbackrest --stanza=demo --type=full backup
text
P00   INFO: execute non-exclusive backup start: backup begins after the requested immediate checkpoint completes
P00   INFO: backup command begin 2.59.1: --exec-id=12345 --log-level-console=warn --pg1-path=/var/lib/postgresql/18/demo ...
P00   INFO: backup start archive = 000000010000000000000005, lsn = 0/5000028
P00   INFO: new backup label = 20260930-020011F
P00   INFO: full backup size = 1200.5MB
P00   INFO: backup command end: completed successfully

示例二:pgBackRest 的「周全量 + 日差异 + 小时增量」 ​

bash
# 周日全量
sudo -u postgres pgbackrest --stanza=demo --type=full backup

# 周一至周六:每天一次差异(相对最近一次全量)
sudo -u postgres pgbackrest --stanza=demo --type=diff backup

# 每小时的增量(相对上一次任意类型备份)
sudo -u postgres pgbackrest --stanza=demo --type=incr backup

# 查看当前备份链
sudo -u postgres pgbackrest --stanza=demo info
text
stanza: demo
    status: ok

    db (current)
        wal archive min/max (18): 000000010000000000000005/00000001000000000000002C

        full backup: 20260927-020011F
            timestamp start/stop: 2026-09-27 02:00:11+08 / 2026-09-27 02:21:37+08
            wal start/stop: 000000010000000000000005 / 00000001000000000000000A
            database size: 1200.5MB, backup size: 1200.5MB

        diff backup: 20260929-020014D
            wal start/stop: 00000001000000000000001C / 00000001000000000000001F
            database size: 1200.5MB, backup size: 96.2MB

        incr backup: 20260930-020017I
            wal start/stop: 000000010000000000000028 / 00000001000000000000002C
            database size: 1200.5MB, backup size: 104.7MB

示例三:pgBackRest 配置 WAL 归档与 PITR 恢复 ​

ini
[global]
repo1-path=/var/lib/pgbackrest
repo1-retention-full=2
repo1-retention-archive-type=full
repo1-retention-archive=2
conf
# postgresql.conf 中让 PostgreSQL 调用 pgBackRest 归档 WAL
archive_mode = on
archive_command = 'pgbackrest --stanza=demo archive-push %p'
bash
# 恢复到某个时间点
sudo -u postgres pgbackrest --stanza=demo \
  --type=time --target="2026-09-30 09:15:00+08" \
  --target-action=promote \
  restore
text
P00   INFO: restore command begin 2.59.1: --exec-id=23456 --stanza=demo --type=time --target="2026-09-30 09:15:00+08" --target-action=promote ...
P00   INFO: restore backup set 20260930-020017I
P00   INFO: write updated /var/lib/postgresql/18/demo/postgresql.auto.conf
P00   INFO: restore global/pg_control (performed last to ensure aborted restores cannot be started)
P00   INFO: restore command end: completed successfully

示例四:Barman 的流式(postgres 方法)备份与 block-level 增量 ​

conf
# /etc/barman.conf
[barman]
barman_home = /var/lib/barman
barman_lock_directory = /var/run/barman
log_file = /var/log/barman/barman.log

[pg]
description = "Primary PostgreSQL 18"
conninfo = host=pg user=barman dbname=postgres
ssh_command = ssh postgres@pg
backup_method = postgres
backup_compression = zstd
backup_compression_format = tar
staging_path = /var/lib/barman/staging
staging_location = local
bash
# 前提:PostgreSQL 端 summarize_wal = on(且早于第一次全量)
barman check pg
barman backup pg

# 基于最近一次全量做块级增量
barman backup --incremental latest-full pg

# 查看备份清单
barman list-backups pg
text
pg 20260928T020011 - Mon Sep 28 02:21:37 2026 - Size: 1.2 GiB - Status: DONE
pg 20260930T020017 - Wed Sep 30 02:19:52 2026 - Size: 1.5 GiB - Status: DONE

示例五:Barman 的 file-level 增量(rsync + 硬链接) ​

conf
[pg]
backup_method = rsync
ssh_command = ssh postgres@pg
reuse_backup = link
bandwidth_limit = 51200
tablespace_bandwidth_limit = tbs_index:20480
bash
# 常规备份就会自动复用上一份(reuse_backup=link)
barman backup pg

# 临时切换策略:这次做「拷贝复用」而不是硬链接
barman backup --reuse-backup=copy pg

示例六:Barman 恢复与 delta-restore 加速 ​

bash
# 1) 普通恢复:恢复到目标目录
barman restore pg latest /var/lib/postgresql/18/main

# 2) 目标目录已有接近的数据时,用 delta-restore 只回填差异
barman restore --delta-restore pg latest /var/lib/postgresql/18/main
conf
# 或在配置中全局启用
[pg]
recovery_options = get-wal,delta-restore

注意事项 ​

pgBackRest 的 backup 默认是 incr。 忘记写 --type=full 时不会得到全量备份,而且第一个备份必须显式指定 full。

链中间不能删。 手工删除仓库里的某个备份(而不是通过 expire)极可能造成断链,让链尾的增量全部失效。只通过 expire 与保留策略来淘汰备份。

WAL 归档保留与备份保留必须一起考虑。 repo1-retention-archive 设置过小会导致「备份还在,但它对应的 WAL 已被清理」,PITR 时就地重放失败。

pgBackRest 的本地与远端版本必须完全一致。 版本不匹配时 WAL 归档与备份都会停止工作,并报 ProtocolError 之类的协商错误;升级时要「一起升」。

别用 root 跑 pgBackRest。 默认只有 restore 命令允许以 root 运行(因为它要精细处理文件属主);其他命令以 root 运行会创建 root 属主的仓库文件,导致后续操作失败。

并发备份没有意义。 多数工具内部已经并行(process-max),再叠加多个备份进程只会同时压榨源库 I/O。

block-level 增量对配置变更敏感。 PG17 原生增量要求 summarize_wal 在第一次全量之前就已开启;Barman 的 block-level 增量还要求两次增量之间不要变更 data_checksums(变更了就该重做全量)。

Barman 的两种增量不可混用。 file-level 与 block-level 之间的父备份不能互相引用;切换类型必须重做全量。

压缩备份需要 staging 才能恢复。 Barman 使用 backup_compression 时必须配 staging_path 与 staging_location;delta-restore 也不适用于 tar 格式。

NFS 上有额外要求。 barman_lock_directory 必须在本地文件系统;NFS 至少 NFSv4,并用 hard,sync 挂载。Barman 官方也明确不推荐「本地备份到 NFS」作为主要方案。

加密口令必须纳入密钥管理。 丢了口令就等于丢了备份;不要把口令与备份放在同一个位置。

增量备份不能替代恢复演练。 备份链越长,恢复路径越复杂。定期做一次「从最旧全量 + 全部增量」的完整恢复演练,才能证明这条链真的可用。

保留策略要按 RPO/RTO 反推。 「保留 2 份全量」意味着最坏情况下你要接受「最近一次全量之后」的丢失窗口,除非有 WAL 归档把窗口压到很小。

最佳实践 ​

  1. 先定 RPO/RTO,再定备份类型与频率。 RPO 决定「WAL 归档 + 增量备份」的频率下限,RTO 决定「保留多少全量、恢复链能有多长」。工具选型放在指标明确之后。

  2. Full / Diff / Incr 三层组合,而不是只做 Full + Incr。 例如「周日 full、每日 diff、每小时 incr」:diff 把恢复链限制在「一份 full + 一份 diff」以内,incr 把备份窗口压到最小。

  3. 保留策略一律交给工具,手工删备份视为事故。 使用 pgbackrest expire / Barman 的保留策略配置,绝不手工 rm 仓库文件;在删除前用 --dry-run 或 list-backups 确认。

  4. 把备份校验做进流程。 pgBackRest 用 verify 校验仓库内容,Barman 用 check / show-backup 确认状态;校验失败立即告警,不许坏备份进入保留期。

bash
sudo -u postgres pgbackrest --stanza=demo verify
barman check pg
  1. 用立即检查点换取可预测的备份窗口。 对时间窗口敏感的场景,开启 pgBackRest 的 start-fast 或 Barman 的 immediate_checkpoint;对在线 I/O 敏感的场景保持默认的摊薄式检查点。

  2. 从备库做备份。 pgBackRest 用 backup-standby,Barman 把 backup_method=postgres 指向备库,可把备份的读取压力从主库移走;注意备库备份对 full_page_writes 等前提的要求。

  3. 性能调优先调并行度,再调压缩级别。 process-max 提高吞吐,压缩级别只影响 CPU 与体积的权衡;在 I/O 受限的环境中,适度降低压缩级别往往整体更快。

  4. 有 VLDB 场景优先考虑块级增量。 pgBackRest 用 repo1-block=y(配合 repo1-bundle=y),Barman 用 --incremental;前者减少仓库重复块,后者减少网络传输量。

  5. 仓库加密默认打开。 pgBackRest 用 repo1-cipher-type=aes-256-cbc,Barman 用 encryption=gpg;口令走密钥管理系统,恢复演练验证口令可用。

  6. 异地/云端必须有一份。 用 pgBackRest 的对象存储仓库,或 Barman 的 barman-cloud-backup 把备份送出去;本地副本用于快恢复,异地副本用于灾难兜底。

bash
barman-cloud-backup --cloud-provider aws-s3 s3://pg-backup/pg pg
  1. 备份标识不可覆盖、命名可追溯。 让工具生成的时间戳标识(20260930-020017I)保持原样,不要在仓库里做自定义重命名,否则元数据与实际内容会脱节。

  2. 每季度做一次「最坏情况」恢复演练。 从最旧的可用全量开始,把整条链恢复到临时实例并用数据校验工具比对,把演练时长记录下来修正 RTO 估算。

下一节

继续学习:文件系统级备份(LVM / ZFS)

参考链接 ​