这是本节的多页打印视图。 点击此处打印.

返回本页常规视图.

备份恢复

时间点恢复(PITR)备份与恢复

Pigsty 使用 pgBackRest 管理 PostgreSQL 备份,这可能是生态系统中最强大的开源备份工具。 它支持增量/并行备份与恢复、加密、MinIO/S3 等众多特性。Pigsty 默认为每个 PGSQL 集群预配置了备份功能。

章节内容
机制备份脚本、定时任务、pgbackrest、仓库与管理
策略备份策略、磁盘规划、恢复窗口权衡
仓库配置备份仓库:本地、MinIO、S3
管理常用备份管理命令
恢复使用剧本恢复到特定时间点
示例沙箱示例:手工执行恢复操作

快速上手

  1. 备份策略:使用 Crontab 调度基础备份
  2. WAL 归档:持续记录写入活动
  3. 恢复与还原:从备份和 WAL 归档中恢复
node_crontab: [ '00 01 * * * postgres /pg/bin/pg-backup full' ]
./pgsql-pitr.yml -e '{"pg_pitr": { "time": "2025-07-13 10:00:00+00" }}'

1 - 备份策略

根据您的需求设计备份策略
  • 何时:备份策略
  • 何处:备份仓库
  • 如何:备份方法

何时备份

第一个问题是何时备份您的数据库——这是备份频率和恢复时间之间的权衡。 由于您需要从上一次备份开始重放 WAL 日志到恢复目标点,备份越频繁,需要重放的 WAL 日志就越少,恢复速度就越快。

每日全量备份

对于生产数据库,建议从最简单的每日全量备份策略开始。 这也是 Pigsty 的默认备份策略,通过 crontab 实现。

node_crontab: [ '00 01 * * * postgres /pg/bin/pg-backup full' ]
pgbackrest_method: local          # 选择备份仓库方法:`local`、`minio` 或其他自定义仓库
pgbackrest_repo:                  # pgbackrest 仓库配置: https://pgbackrest.org/configuration.html#section-repository
  local:                          # 使用本地 POSIX 文件系统的默认 pgbackrest 仓库
    path: /pg/backup              # 本地备份目录,默认为 `/pg/backup`
    retention_full_type: count    # 按数量保留全量备份
    retention_full: 2             # 使用本地文件系统仓库时,保留2个,最多3个全量备份

配合默认的 local 本地文件系统备份仓库使用时,可提供 24~48 小时的恢复窗口。

pitr-scope

假设您的数据库大小为 100GB,每天写入 10GB 数据,则备份大小如下:

pitr-space

这将消耗数据库大小的 2~3 倍空间,再加上 2 天的 WAL 日志。 因此在实践中,您可能需要准备至少 3~5 倍数据库大小的备份磁盘才能使用默认备份策略。

全量 + 增量备份

您可以通过调整这些参数来优化备份空间使用。

如果使用 MinIO / S3 作为集中式备份仓库,您可以使用超出本地磁盘限制的存储空间。 此时可以考虑使用全量 + 增量备份配合 2 周保留策略:

node_crontab:  # 周一凌晨1点全量备份,工作日增量备份
  - '00 01 * * 1 postgres /pg/bin/pg-backup full'
  - '00 01 * * 2,3,4,5,6,7 postgres /pg/bin/pg-backup'
pgbackrest_method: minio
pgbackrest_repo:                  # pgbackrest 仓库配置: https://pgbackrest.org/configuration.html#section-repository
  minio:                          # 可选的 minio 仓库
    type: s3                      # minio 兼容 S3 协议
    s3_endpoint: sss.pigsty       # minio 端点域名,默认为 `sss.pigsty`
    s3_region: us-east-1          # minio 区域,默认 us-east-1,对 minio 无实际意义
    s3_bucket: pgsql              # minio 桶名,默认为 `pgsql`
    s3_key: pgbackrest            # pgbackrest 的 minio 用户访问密钥
    s3_key_secret: S3User.Backup  # pgbackrest 的 minio 用户密钥
    s3_uri_style: path            # minio 使用路径风格 URI 而非主机风格
    path: /pgbackrest             # minio 备份路径,默认为 `/pgbackrest`
    storage_port: 9000            # minio 端口,默认 9000
    storage_ca_file: /etc/pki/ca.crt  # minio CA 证书路径,默认 `/etc/pki/ca.crt`
    block: y                      # 启用块级增量备份
    bundle: y                     # 将小文件打包成单个文件
    bundle_limit: 20MiB           # 文件包大小限制,对象存储建议 20MiB
    bundle_size: 128MiB           # 文件包目标大小,对象存储建议 128MiB
    cipher_type: aes-256-cbc      # 为远程备份仓库启用 AES 加密
    cipher_pass: pgBackRest       # AES 加密密码,默认为 'pgBackRest'
    retention_full_type: time     # 按时间保留全量备份
    retention_full: 14            # 保留最近 14 天的全量备份

配合内置的 minio 备份仓库使用时,可提供保证 1 周的 PITR 恢复窗口。

pitr-scope2

假设您的数据库大小为 100GB,每天写入 10GB 数据,则备份大小如下:

pitr-space2


备份位置

默认情况下,Pigsty 提供两个默认备份仓库定义:localminio 备份仓库。

  • local默认选项,使用本地 /pg/backup 目录(软链接指向 pg_fs_backup/data/backups
  • minio:使用 SNSD 单节点 MinIO 集群(Pigsty 支持,但默认不启用)
pgbackrest_method: local          # 选择备份仓库方法:`local`、`minio` 或其他自定义仓库
pgbackrest_repo:                  # pgbackrest 仓库配置: https://pgbackrest.org/configuration.html#section-repository
  local:                          # 使用本地 POSIX 文件系统的默认 pgbackrest 仓库
    path: /pg/backup              # 本地备份目录,默认为 `/pg/backup`
    retention_full_type: count    # 按数量保留全量备份
    retention_full: 2             # 使用本地文件系统仓库时,保留2个,最多3个全量备份
  minio:                          # 可选的 minio 仓库
    type: s3                      # minio 兼容 S3 协议
    s3_endpoint: sss.pigsty       # minio 端点域名,默认为 `sss.pigsty`
    s3_region: us-east-1          # minio 区域,默认 us-east-1,对 minio 无实际意义
    s3_bucket: pgsql              # minio 桶名,默认为 `pgsql`
    s3_key: pgbackrest            # pgbackrest 的 minio 用户访问密钥
    s3_key_secret: S3User.Backup  # pgbackrest 的 minio 用户密钥
    s3_uri_style: path            # minio 使用路径风格 URI 而非主机风格
    path: /pgbackrest             # minio 备份路径,默认为 `/pgbackrest`
    storage_port: 9000            # minio 端口,默认 9000
    storage_ca_file: /etc/pki/ca.crt  # minio CA 证书路径,默认 `/etc/pki/ca.crt`
    block: y                      # 启用块级增量备份
    bundle: y                     # 将小文件打包成单个文件
    bundle_limit: 20MiB           # 文件包大小限制,对象存储建议 20MiB
    bundle_size: 128MiB           # 文件包目标大小,对象存储建议 128MiB
    cipher_type: aes-256-cbc      # 为远程备份仓库启用 AES 加密
    cipher_pass: pgBackRest       # AES 加密密码,默认为 'pgBackRest'
    retention_full_type: time     # 按时间保留全量备份
    retention_full: 14            # 保留最近 14 天的全量备份

2 - 备份机制

备份脚本、定时任务、备份仓库与基础设施

备份可以通过内置脚本调用,使用节点 crontab 定时执行, 由 pgbackrest 管理,存储在备份仓库中, 仓库可以是本地磁盘文件系统或 MinIO / S3,并支持不同的保留策略。


脚本

您可以使用 pg_dbsu 用户(默认为 postgres)执行 pgbackrest 命令创建备份:

pgbackrest --stanza=pg-meta --type=full backup   # 为集群 pg-meta 创建全量备份
$ pgbackrest --stanza=pg-meta --type=full backup
2025-07-15 01:36:57.007 P00   INFO: backup command begin 2.54.2: --annotation=pg_cluster=pg-meta ...
2025-07-15 01:36:57.030 P00   INFO: execute non-exclusive backup start: backup begins after the requested immediate checkpoint completes
2025-07-15 01:36:57.105 P00   INFO: backup start archive = 000000010000000000000006, lsn = 0/6000028
2025-07-15 01:36:58.540 P00   INFO: new backup label = 20250715-013657F
2025-07-15 01:36:58.588 P00   INFO: full backup size = 44.5MB, file total = 1437
2025-07-15 01:36:58.589 P00   INFO: backup command end: completed successfully (1584ms)
$ pgbackrest --stanza=pg-meta --type=diff backup
2025-07-15 01:37:24.952 P00   INFO: backup command begin 2.54.2: ...
2025-07-15 01:37:24.985 P00   INFO: last backup label = 20250715-013657F, version = 2.54.2
2025-07-15 01:37:26.337 P00   INFO: new backup label = 20250715-013657F_20250715-013724D
2025-07-15 01:37:26.381 P00   INFO: diff backup size = 424.3KB, file total = 1437
2025-07-15 01:37:26.381 P00   INFO: backup command end: completed successfully (1431ms)
$ pgbackrest --stanza=pg-meta --type=incr backup
2025-07-15 01:37:30.305 P00   INFO: backup command begin 2.54.2: ...
2025-07-15 01:37:30.337 P00   INFO: last backup label = 20250715-013657F_20250715-013724D, version = 2.54.2
2025-07-15 01:37:31.356 P00   INFO: new backup label = 20250715-013657F_20250715-013730I
2025-07-15 01:37:31.403 P00   INFO: incr backup size = 8.3KB, file total = 1437
2025-07-15 01:37:31.403 P00   INFO: backup command end: completed successfully (1099ms)
$ pgbackrest --stanza=pg-meta info
stanza: pg-meta
    status: ok
    cipher: aes-256-cbc

    db (current)
        wal archive min/max (17): 000000010000000000000001/00000001000000000000000A

        full backup: 20250715-013657F
            timestamp start/stop: 2025-07-15 01:36:57+00 / 2025-07-15 01:36:58+00
            wal start/stop: 000000010000000000000006 / 000000010000000000000006
            database size: 44.5MB, database backup size: 44.5MB
            repo1: backup size: 8.7MB

        diff backup: 20250715-013657F_20250715-013724D
            timestamp start/stop: 2025-07-15 01:37:24+00 / 2025-07-15 01:37:26+00
            database size: 44.5MB, database backup size: 424.3KB
            repo1: backup size: 94KB
            backup reference total: 1 full

        incr backup: 20250715-013657F_20250715-013730I
            timestamp start/stop: 2025-07-15 01:37:30+00 / 2025-07-15 01:37:31+00
            database size: 44.5MB, database backup size: 8.3KB
            repo1: backup size: 504B
            backup reference total: 1 full, 1 diff

这里的 stanza 是数据库集群名称:pg_cluster,在默认配置中为 pg-meta

Pigsty 提供了 pb 别名和 pg-backup 包装脚本,会自动填充当前集群名称作为 stanza:

function pb() {
    local stanza=$(grep -o '\[[^][]*]' /etc/pgbackrest/pgbackrest.conf | head -n1 | sed 's/.*\[\([^]]*\)].*/\1/')
    pgbackrest --stanza=$stanza $@
}
pb ...    # pgbackrest --stanza=pg-meta ...
pb info   # pgbackrest --stanza=pg-meta info
pb backup # pgbackrest --stanza=pg-meta backup
pg-backup full   # 执行全量备份         = pgbackrest --stanza=pg-meta --type=full backup
pg-backup incr   # 执行增量备份         = pgbackrest --stanza=pg-meta --type=incr backup
pg-backup diff   # 执行差异备份         = pgbackrest --stanza=pg-meta --type=diff backup

定时备份

Pigsty 利用 Linux crontab 来调度备份任务。您可以用它定义备份策略。

例如,大多数单节点配置模板都有以下用于备份的 node_crontab

node_crontab: [ '00 01 * * * postgres /pg/bin/pg-backup full' ]

您可以使用 crontab 和 pg-backup 脚本设计更复杂的备份策略,例如:

node_crontab:  # 周一凌晨1点全量备份,工作日增量备份
  - '00 01 * * 1 postgres /pg/bin/pg-backup full'
  - '00 01 * * 2,3,4,5,6,7 postgres /pg/bin/pg-backup'

要应用 crontab 变更,使用 node.yml 更新所有节点的 crontab:

./node.yml -t node_crontab -l pg-meta    # 将 crontab 变更应用到 pg-meta 组

pgbackrest

以下是 Pigsty 对 pgbackrest 的配置细节:

文件层次结构

  • bin:/usr/bin/pgbackrest,来自 PGDG 的 pgbackrest 包,在组别名 pgsql-common 中。
  • conf:/etc/pgbackrest,主配置文件是 /etc/pgbackrest/pgbackrest.conf
  • logs:/pg/log/pgbackrest/*,由 pgbackrest_log_dir 控制
  • tmp:/pg/spool 用作 pgbackrest 的临时 spool 目录
  • data:/pg/backup 用于存储数据(当选择默认的 local 文件系统备份仓库时)

此外,在 PITR 恢复过程中,Pigsty 会创建临时的 /pg/conf/pitr.conf pgbackrest 配置文件, 并将 postgres 恢复日志写入 /pg/tmp/recovery.log 文件。

监控

有一个 pgbackrest_exporter 服务运行在 pgbackrest_exporter_port9854)端口上,用于导出 pgbackrest 指标。 您可以通过 pgbackrest_exporter_options 自定义它, 或将 pgbackrest_exporter_enabled 设置为 false 来禁用它。

初始备份

当创建 postgres 集群时,Pigsty 会自动创建初始备份。 由于新集群几乎为空,这是一个很小的备份。 它会留下一个 /etc/pgbackrest/initial.done 标记文件,以避免重复创建初始备份。 如果不需要初始备份,请将 pgbackrest_init_backup 设置为 false


管理

启用备份

如果数据库集群创建时 pgbackrest_enabled 设置为 true,备份将自动启用。

如果创建时该值为 false,您可以使用以下命令启用 pgbackrest 组件:

./pgsql.yml -t pg_backup    # 运行 pgbackrest 子任务

删除备份

当移除主实例(pg_role = primary)时,Pigsty 会删除 pgbackrest 备份 stanza。

./pgsql-rm.yml
./pgsql-rm.yml -e pg_rm_backup=false   # 保留备份
./pgsql-rm.yml -t pg_backup            # 仅删除备份

使用 pg_backup 子任务仅删除备份,使用 keep_backup 参数保留备份。

如果您的备份仓库被锁定(例如 S3 / MinIO 有锁定选项),此操作将失败。

列出备份

此命令将列出 pgbackrest 仓库中的所有备份(所有集群共享)

pgbackrest info

手动备份

Pigsty 提供了内置脚本 /pg/bin/pg-backup,封装了 pgbackrest 备份命令。

pg-backup        # 执行增量备份
pg-backup full   # 执行全量备份
pg-backup incr   # 执行增量备份
pg-backup diff   # 执行差异备份

基础备份

Pigsty 提供了一个替代备份脚本 /pg/bin/pg-basebackup,它不依赖 pgbackrest,直接提供数据库集群的物理副本。 默认备份目录为 /pg/backup

NAME
  pg-basebackup  -- make base backup from PostgreSQL instance

SYNOPSIS
  pg-basebackup -sdfeukr
  pg-basebackup --src postgres:/// --dst . --file backup.tar.lz4

DESCRIPTION
-s, --src, --url     备份源 URL,可选,默认为 "postgres:///",如需密码应在 url、ENV 或 .pgpass 中提供
-d, --dst, --dir     备份文件存放位置,默认为 "/pg/backup"
-f, --file           覆盖默认备份文件名,"backup_${tag}_${date}.tar.lz4"
-r, --remove         删除 n 分钟前的 .lz4 文件,默认 1200(20小时)
-t, --tag            备份文件标签,未设置时使用目标集群名或本地 IP 地址,也用于默认文件名
-k, --key            指定 --encrypt 时的加密密钥,默认密钥为 ${tag}
-u, --upload         上传备份文件到云存储(需自行实现)
-e, --encryption     使用 OpenSSL RC4 加密,未指定密钥时使用 tag 作为密钥
-h, --help           打印此帮助信息
postgres@pg-meta-1:~$ pg-basebackup
[2025-07-13 06:16:05][INFO] ================================================================
[2025-07-13 06:16:05][INFO] [INIT] pg-basebackup begin, checking parameters
[2025-07-13 06:16:05][DEBUG] [INIT] filename  (-f)    :   backup_pg-meta_20250713.tar.lz4
[2025-07-13 06:16:05][DEBUG] [INIT] src       (-s)    :   postgres:///
[2025-07-13 06:16:05][DEBUG] [INIT] dst       (-d)    :   /pg/backup
[2025-07-13 06:16:05][INFO] [LOCK] lock acquired success on /tmp/backup.lock, pid=107417
[2025-07-13 06:16:05][INFO] [BKUP] backup begin, from postgres:/// to /pg/backup/backup_pg-meta_20250713.tar.lz4
pg_basebackup: initiating base backup, waiting for checkpoint to complete
pg_basebackup: checkpoint completed
pg_basebackup: write-ahead log start point: 0/7000028 on timeline 1
pg_basebackup: write-ahead log end point: 0/7000FD8
pg_basebackup: syncing data to disk ...
pg_basebackup: base backup completed
[2025-07-13 06:16:06][INFO] [BKUP] backup complete!
[2025-07-13 06:16:06][INFO] [DONE] backup procedure complete!
[2025-07-13 06:16:06][INFO] ================================================================

备份使用 lz4 压缩。您可以使用以下命令解压并提取 tarball:

mkdir -p /tmp/data   # 将备份提取到此目录
cat /pg/backup/backup_pg-meta_20250713.tar.lz4 | unlz4 -d -c | tar -xC /tmp/data

逻辑备份

您也可以使用 pg_dump 命令执行逻辑备份。

逻辑备份不能用于 PITR(时间点恢复),但对于在不同主版本之间迁移数据或实现灵活的数据导出逻辑非常有用。

从仓库引导

假设您有一个现有集群 pg-meta,想要将其克隆pg-meta2

您需要创建新的 pg-meta2 集群分支,然后在其上运行 pitr

3 - 备份仓库

PostgreSQL 备份存储仓库配置

您可以通过指定 pgbackrest_repo 参数来配置备份存储位置。 您可以在此定义多个仓库,Pigsty 会根据 pgbackrest_method 的值选择使用哪个。

默认仓库

默认情况下,Pigsty 提供两个默认备份仓库定义:localminio 备份仓库。

  • local默认选项,使用本地 /pg/backup 目录(软链接指向 pg_fs_backup/data/backups
  • minio:使用 SNSD 单节点 MinIO 集群(Pigsty 支持,但默认不启用)
pgbackrest_method: local          # 选择备份仓库方法:`local`、`minio` 或其他自定义仓库
pgbackrest_repo:                  # pgbackrest 仓库配置: https://pgbackrest.org/configuration.html#section-repository
  local:                          # 使用本地 POSIX 文件系统的默认 pgbackrest 仓库
    path: /pg/backup              # 本地备份目录,默认为 `/pg/backup`
    retention_full_type: count    # 按数量保留全量备份
    retention_full: 2             # 使用本地文件系统仓库时,保留2个,最多3个全量备份
  minio:                          # 可选的 minio 仓库
    type: s3                      # minio 兼容 S3 协议
    s3_endpoint: sss.pigsty       # minio 端点域名,默认为 `sss.pigsty`
    s3_region: us-east-1          # minio 区域,默认 us-east-1,对 minio 无实际意义
    s3_bucket: pgsql              # minio 桶名,默认为 `pgsql`
    s3_key: pgbackrest            # pgbackrest 的 minio 用户访问密钥
    s3_key_secret: S3User.Backup  # pgbackrest 的 minio 用户密钥
    s3_uri_style: path            # minio 使用路径风格 URI 而非主机风格
    path: /pgbackrest             # minio 备份路径,默认为 `/pgbackrest`
    storage_port: 9000            # minio 端口,默认 9000
    storage_ca_file: /etc/pki/ca.crt  # minio CA 证书路径,默认 `/etc/pki/ca.crt`
    block: y                      # 启用块级增量备份
    bundle: y                     # 将小文件打包成单个文件
    bundle_limit: 20MiB           # 文件包大小限制,对象存储建议 20MiB
    bundle_size: 128MiB           # 文件包目标大小,对象存储建议 128MiB
    cipher_type: aes-256-cbc      # 为远程备份仓库启用 AES 加密
    cipher_pass: pgBackRest       # AES 加密密码,默认为 'pgBackRest'
    retention_full_type: time     # 按时间保留全量备份
    retention_full: 14            # 保留最近 14 天的全量备份

仓库保留策略

如果每天备份但不删除旧备份,备份仓库会不断增长并耗尽磁盘空间。 您需要定义保留策略,只保留有限数量的备份。

默认备份策略定义在 pgbackrest_repo 参数中,可按需调整。

  • local:保留最近 2 个全量备份,备份期间最多允许 3 个
  • minio:保留最近 14 天的所有全量备份

空间规划

对象存储提供几乎无限的存储容量,因此无需担心磁盘空间。 您可以使用混合的全量 + 差异备份策略来优化空间使用。

对于本地磁盘备份仓库,Pigsty 建议使用保留最近 2 个全量备份的策略, 这意味着磁盘上保留两个最新的全量备份(运行新备份时可能存在第三个副本)。

这可保证至少 24 小时的恢复窗口。详情请参阅备份策略


其他仓库选项

您也可以使用其他服务作为备份仓库,详情请参阅 pgbackrest 文档


仓库版本控制

您甚至可以指定 repo target time 来获取对象存储的快照。

您可以通过在 minio_buckets 中添加 versioning 标志来启用 MinIO 版本控制:

minio_buckets:
  - { name: pgsql ,versioning: true }
  - { name: meta  ,versioning: true }
  - { name: data }

仓库锁定

某些对象存储服务(S3、MinIO 等)支持锁定功能,可以防止备份被删除,即使是 DBA 本人也无法删除。

您可以通过在 minio_buckets 中添加 lock 标志来启用 MinIO 锁定功能:

minio_buckets:
  - { name: pgsql , lock: true }
  - { name: meta ,versioning: true  }
  - { name: data }

使用对象存储

对象存储服务提供几乎无限的存储容量,并为您的系统提供远程容灾能力。 如果您没有对象存储服务,Pigsty 内置了 MinIO 支持。

MinIO

您可以通过取消注释以下设置来启用 MinIO 备份仓库。 请注意 pgbackrest 只支持 HTTPS / 域名,因此您必须使用域名和 HTTPS 端点运行 MinIO。

all:
  vars:
    pgbackrest_method: minio      # 使用 minio 作为默认备份仓库
  children:                       # 定义一个单节点 minio SNSD 集群
    minio: { hosts: { 10.10.10.10: { minio_seq: 1 }} ,vars: { minio_cluster: minio }}

S3

如果您只有一个节点,有意义的备份策略可以是使用云厂商的对象存储服务,如 AWS S3、阿里云 OSS 或 Google Cloud 等。 为此,您可以定义一个新仓库:

pgbackrest_method: s3             # 使用 'pgbackrest_repo.s3' 作为备份仓库
pgbackrest_repo:                  # pgbackrest 仓库配置: https://pgbackrest.org/configuration.html#section-repository

  s3:                             # 阿里云 OSS(S3 兼容)对象存储服务
    type: s3                      # oss 兼容 S3 协议
    s3_endpoint: oss-cn-beijing-internal.aliyuncs.com
    s3_region: oss-cn-beijing
    s3_bucket: <your_bucket_name>
    s3_key: <your_access_key>
    s3_key_secret: <your_secret_key>
    s3_uri_style: host
    path: /pgbackrest
    bundle: y                     # 将小文件打包成单个文件
    bundle_limit: 20MiB           # 文件包大小限制,对象存储建议 20MiB
    bundle_size: 128MiB           # 文件包目标大小,对象存储建议 128MiB
    cipher_type: aes-256-cbc      # 为远程备份仓库启用 AES 加密
    cipher_pass: pgBackRest       # AES 加密密码,默认为 'pgBackRest'
    retention_full_type: time     # 按时间保留全量备份
    retention_full: 14            # 保留最近 14 天的全量备份

  local:                          # 使用本地 POSIX 文件系统的默认 pgbackrest 仓库
    path: /pg/backup              # 本地备份目录,默认为 `/pg/backup`
    retention_full_type: count    # 按数量保留全量备份
    retention_full: 2             # 使用本地文件系统仓库时,保留2个,最多3个全量备份

管理备份

启用备份

如果数据库集群创建时 pgbackrest_enabled 设置为 true,备份将自动启用。

如果创建时该值为 false,您可以使用以下命令启用 pgbackrest 组件:

./pgsql.yml -t pg_backup    # 运行 pgbackrest 子任务

删除备份

当移除主实例(pg_role = primary)时,Pigsty 会删除 pgbackrest 备份 stanza。

./pgsql-rm.yml
./pgsql-rm.yml -e pg_rm_backup=false   # 保留备份
./pgsql-rm.yml -t pg_backup            # 仅删除备份

使用 pg_backup 子任务仅删除备份,使用 keep_backup 参数保留备份。

如果您的备份仓库被锁定(例如 S3 / MinIO 有锁定选项),此操作将失败。

列出备份

此命令将列出 pgbackrest 仓库中的所有备份(所有集群共享)

pgbackrest info

手动备份

Pigsty 提供了内置脚本 /pg/bin/pg-backup,封装了 pgbackrest 备份命令。

pg-backup        # 执行增量备份
pg-backup full   # 执行全量备份
pg-backup incr   # 执行增量备份
pg-backup diff   # 执行差异备份

基础备份

Pigsty 提供了一个替代备份脚本 /pg/bin/pg-basebackup,它不依赖 pgbackrest,直接提供数据库集群的物理副本。 默认备份目录为 /pg/backup

NAME
  pg-basebackup  -- make base backup from PostgreSQL instance

SYNOPSIS
  pg-basebackup -sdfeukr
  pg-basebackup --src postgres:/// --dst . --file backup.tar.lz4

DESCRIPTION
-s, --src, --url     备份源 URL,可选,默认为 "postgres:///",如需密码应在 url、ENV 或 .pgpass 中提供
-d, --dst, --dir     备份文件存放位置,默认为 "/pg/backup"
-f, --file           覆盖默认备份文件名,"backup_${tag}_${date}.tar.lz4"
-r, --remove         删除 n 分钟前的 .lz4 文件,默认 1200(20小时)
-t, --tag            备份文件标签,未设置时使用目标集群名或本地 IP 地址,也用于默认文件名
-k, --key            指定 --encrypt 时的加密密钥,默认密钥为 ${tag}
-u, --upload         上传备份文件到云存储(需自行实现)
-e, --encryption     使用 OpenSSL RC4 加密,未指定密钥时使用 tag 作为密钥
-h, --help           打印此帮助信息
postgres@pg-meta-1:~$ pg-basebackup
[2025-07-13 06:16:05][INFO] ================================================================
[2025-07-13 06:16:05][INFO] [INIT] pg-basebackup begin, checking parameters
[2025-07-13 06:16:05][DEBUG] [INIT] filename  (-f)    :   backup_pg-meta_20250713.tar.lz4
[2025-07-13 06:16:05][DEBUG] [INIT] src       (-s)    :   postgres:///
[2025-07-13 06:16:05][DEBUG] [INIT] dst       (-d)    :   /pg/backup
[2025-07-13 06:16:05][INFO] [LOCK] lock acquired success on /tmp/backup.lock, pid=107417
[2025-07-13 06:16:05][INFO] [BKUP] backup begin, from postgres:/// to /pg/backup/backup_pg-meta_20250713.tar.lz4
pg_basebackup: initiating base backup, waiting for checkpoint to complete
pg_basebackup: checkpoint completed
pg_basebackup: write-ahead log start point: 0/7000028 on timeline 1
pg_basebackup: write-ahead log end point: 0/7000FD8
pg_basebackup: syncing data to disk ...
pg_basebackup: base backup completed
[2025-07-13 06:16:06][INFO] [BKUP] backup complete!
[2025-07-13 06:16:06][INFO] [DONE] backup procedure complete!
[2025-07-13 06:16:06][INFO] ================================================================

备份使用 lz4 压缩。您可以使用以下命令解压并提取 tarball:

mkdir -p /tmp/data   # 将备份提取到此目录
cat /pg/backup/backup_pg-meta_20250713.tar.lz4 | unlz4 -d -c | tar -xC /tmp/data

逻辑备份

您也可以使用 pg_dump 命令执行逻辑备份。

逻辑备份不能用于 PITR(时间点恢复),但对于在不同主版本之间迁移数据或实现灵活的数据导出逻辑非常有用。

从仓库引导

假设您有一个现有集群 pg-meta,想要将其克隆pg-meta2

您需要创建新的 pg-meta2 集群分支,然后在其上运行 pitr

4 - 管理命令

管理备份仓库和备份

启用备份

如果数据库集群创建时 pgbackrest_enabled 设置为 true,备份将自动启用。

如果创建时该值为 false,您可以使用以下命令启用 pgbackrest 组件:

./pgsql.yml -t pg_backup    # 运行 pgbackrest 子任务

删除备份

当移除主实例(pg_role = primary)时,Pigsty 会删除 pgbackrest 备份 stanza。

./pgsql-rm.yml
./pgsql-rm.yml -e pg_rm_backup=false   # 保留备份
./pgsql-rm.yml -t pg_backup            # 仅删除备份

使用 pg_backup 子任务仅删除备份,使用 keep_backup 参数保留备份。

如果您的备份仓库被锁定(例如 S3 / MinIO 有锁定选项),此操作将失败。


列出备份

此命令将列出 pgbackrest 仓库中的所有备份(所有集群共享)

pgbackrest info

手动备份

Pigsty 提供了内置脚本 /pg/bin/pg-backup,封装了 pgbackrest 备份命令。

pg-backup        # 执行增量备份
pg-backup full   # 执行全量备份
pg-backup incr   # 执行增量备份
pg-backup diff   # 执行差异备份

基础备份

Pigsty 提供了一个替代备份脚本 /pg/bin/pg-basebackup,它不依赖 pgbackrest,直接提供数据库集群的物理副本。 默认备份目录为 /pg/backup

NAME
  pg-basebackup  -- make base backup from PostgreSQL instance

SYNOPSIS
  pg-basebackup -sdfeukr
  pg-basebackup --src postgres:/// --dst . --file backup.tar.lz4

DESCRIPTION
-s, --src, --url     备份源 URL,可选,默认为 "postgres:///",如需密码应在 url、ENV 或 .pgpass 中提供
-d, --dst, --dir     备份文件存放位置,默认为 "/pg/backup"
-f, --file           覆盖默认备份文件名,"backup_${tag}_${date}.tar.lz4"
-r, --remove         删除 n 分钟前的 .lz4 文件,默认 1200(20小时)
-t, --tag            备份文件标签,未设置时使用目标集群名或本地 IP 地址,也用于默认文件名
-k, --key            指定 --encrypt 时的加密密钥,默认密钥为 ${tag}
-u, --upload         上传备份文件到云存储(需自行实现)
-e, --encryption     使用 OpenSSL RC4 加密,未指定密钥时使用 tag 作为密钥
-h, --help           打印此帮助信息
postgres@pg-meta-1:~$ pg-basebackup
[2025-07-13 06:16:05][INFO] ================================================================
[2025-07-13 06:16:05][INFO] [INIT] pg-basebackup begin, checking parameters
[2025-07-13 06:16:05][DEBUG] [INIT] filename  (-f)    :   backup_pg-meta_20250713.tar.lz4
[2025-07-13 06:16:05][DEBUG] [INIT] src       (-s)    :   postgres:///
[2025-07-13 06:16:05][DEBUG] [INIT] dst       (-d)    :   /pg/backup
[2025-07-13 06:16:05][INFO] [LOCK] lock acquired success on /tmp/backup.lock, pid=107417
[2025-07-13 06:16:05][INFO] [BKUP] backup begin, from postgres:/// to /pg/backup/backup_pg-meta_20250713.tar.lz4
pg_basebackup: initiating base backup, waiting for checkpoint to complete
pg_basebackup: checkpoint completed
pg_basebackup: write-ahead log start point: 0/7000028 on timeline 1
pg_basebackup: write-ahead log end point: 0/7000FD8
pg_basebackup: syncing data to disk ...
pg_basebackup: base backup completed
[2025-07-13 06:16:06][INFO] [BKUP] backup complete!
[2025-07-13 06:16:06][INFO] [DONE] backup procedure complete!
[2025-07-13 06:16:06][INFO] ================================================================

备份使用 lz4 压缩。您可以使用以下命令解压并提取 tarball:

mkdir -p /tmp/data   # 将备份提取到此目录
cat /pg/backup/backup_pg-meta_20250713.tar.lz4 | unlz4 -d -c | tar -xC /tmp/data

逻辑备份

您也可以使用 pg_dump 命令执行逻辑备份。

逻辑备份不能用于 PITR(时间点恢复),但对于在不同主版本之间迁移数据或实现灵活的数据导出逻辑非常有用。


从仓库引导

假设您有一个现有集群 pg-meta,想要将其克隆pg-meta2

您需要创建新的 pg-meta2 集群分支,然后在其上运行 pitr

5 - 恢复操作

从备份恢复 PostgreSQL

您可以使用预配置的 pgbackrest 在 Pigsty 中执行时间点恢复(PITR)。

  • 手动方式:使用 pg-pitr 提示脚本手动执行 PITR,更灵活但更复杂。
  • 剧本方式:使用 pgsql-pitr.yml 剧本自动执行 PITR,自动化程度高但灵活性较低,容易出错。

如果您对配置非常熟悉,可以使用全自动剧本,否则建议手动逐步操作。


快速上手

如果您想将 pg-meta 集群回滚到之前的时间点,添加 pg_pitr 参数:

pg-meta:
  hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } }
  vars:
    pg_cluster: pg-meta2
    pg_pitr: { time: '2025-07-13 10:00:00+00' }  # 从最新备份恢复

然后运行 pgsql-pitr.yml 剧本,它将把 pg-meta 集群回滚到指定时间点。

./pgsql-pitr.yml -l pg-meta

恢复后处理

恢复后的集群会禁用 archive_mode,以防止意外的 WAL 写入。 如果恢复后的数据库状态正常,您可以启用 archive_mode 并执行全量备份。

psql -c 'ALTER SYSTEM RESET archive_mode; SELECT pg_reload_conf();'
pg-backup full    # 执行新的全量备份

恢复目标

您可以在 pg_pitr 中指定不同类型的恢复目标,但它们是互斥的:

  • time:恢复到哪个时间点?
  • name:恢复到命名的恢复点(由 pg_create_restore_point 创建)
  • xid:恢复到特定的事务 ID(TXID/XID)
  • lsn:恢复到特定的 LSN(日志序列号)点

如果指定了上述任何参数,恢复类型会相应设置, 否则将设置为 latest(WAL 归档流的末尾)。 特殊的 immediate 类型可用于指示 pgbackrest 通过在第一个一致点停止来最小化恢复时间。

目标类型

pg_pitr: { }  # 恢复到最新状态(WAL 归档流末尾)
pg_pitr: { time: "2025-07-13 10:00:00+00" }
pg_pitr: { lsn: "0/4001C80" }
pg_pitr: { xid: "250000" }
pg_pitr: { name: "some_restore_point" }
pg_pitr: { type: "immediate" }

按时间恢复

最常用的目标是时间点;您可以指定要恢复到的时间点:

./pgsql-pitr.yml -e '{"pg_pitr": { "time": "2025-07-13 10:00:00+00" }}'

时间应该是有效的 PostgreSQL TIMESTAMP 格式,建议使用 YYYY-MM-DD HH:MM:SS+TZ

按名称恢复

您可以使用 pg_create_restore_point 创建命名恢复点:

SELECT pg_create_restore_point('shit_incoming');

然后在 PITR 中使用该命名恢复点:

./pgsql-pitr.yml -e '{"pg_pitr": { "name": "shit_incoming" }}'

按 XID 恢复

如果您有一个事务意外删除了某些数据,最好的恢复方式是将数据库恢复到该事务之前的状态。

./pgsql-pitr.yml -e '{"pg_pitr": { "xid": "250000", exclusive: true }}'

您可以从监控仪表盘找到确切的事务 ID,或从 CSVLOG 中的 TXID 字段获取。

按 LSN 恢复

PostgreSQL 使用 LSN(日志序列号)来标识 WAL 记录的位置。 您可以在很多地方找到它,比如 Pigsty 仪表盘的 PG LSN 面板。

./pgsql-pitr.yml -e '{"pg_pitr": { "lsn": "0/4001C80", timeline: "1" }}'

要恢复到 WAL 流中的确切位置,您还可以指定 timeline 参数(默认为 latest


恢复来源

  • cluster:从哪个集群恢复?默认使用当前的 pg_cluster,您可以使用同一 pgbackrest 仓库中的任何其他集群
  • repo:覆盖备份仓库,使用与 pgbackrest_repo 相同的格式
  • set:默认使用 latest 备份集,但您可以通过标签指定特定的 pgbackrest 备份

Pigsty 将从 pgbackrest 备份仓库恢复。如果您使用集中式备份仓库(如 MinIO/S3), 可以指定另一个 “stanza”(另一个集群的备份目录)作为恢复来源。

pg-meta2:
  hosts: { 10.10.10.11: { pg_seq: 1, pg_role: primary } }
  vars:
    pg_cluster: pg-meta2
    pg_pitr: { cluster: pg-meta }  # 从 pg-meta 集群备份恢复

上述配置将标记 PITR 过程使用 pg-meta stanza。 您也可以通过 CLI 参数传递 pg_pitr 参数:

./pgsql-pitr.yml -l pg-meta2 -e '{"pg_pitr": { "cluster": "pg-meta" }}'

从另一个集群 PITR 时也可以使用这些目标:

./pgsql-pitr.yml -l pg-meta2 -e '{"pg_pitr": { "cluster": "pg-meta", "time": "2025-07-14 08:00:00+00" }}'

分步执行

这种方式是半自动的,您将参与 PITR 过程以做出关键决策。

例如,此配置将把 pg-meta 集群本身恢复到指定时间点:

pg-meta:
  hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } }
  vars:
    pg_cluster: pg-meta2
    pg_pitr: { time: '2025-07-13 10:00:00+00' }  # 从最新备份恢复

让我们逐步执行:

./pgsql-pitr.yml -l pg-meta -t down     # 暂停 patroni 高可用
./pgsql-pitr.yml -l pg-meta -t pitr     # 运行 pitr 过程
./pgsql-pitr.yml -l pg-meta -t up       # 生成 pgbackrest 配置和恢复脚本
# down                 : # 停止高可用并关闭 patroni 和 postgres
#   - pause            : # 暂停 patroni 自动故障切换
#   - stop             : # 停止 patroni 和 postgres 服务
#     - stop_patroni   : # 停止 patroni 服务
#     - stop_postgres  : # 停止 postgres 服务
# pitr                 : # 执行 PITR 过程
#   - config           : # 生成 pgbackrest 配置和恢复脚本
#   - restore          : # 运行 pgbackrest 恢复命令
#   - recovery         : # 启动 postgres 并完成恢复
#   - verify           : # 验证恢复后的集群控制数据
# up:                  : # 启动 postgres / patroni 并恢复高可用
#   - etcd             : # 启动前清理 etcd 元数据
#   - start            : # 启动 patroni 和 postgres 服务
#     - start_postgres : # 启动 postgres 服务
#     - start_patroni  : # 启动 patroni 服务
#   - resume           : # 恢复 patroni 自动故障切换

PITR 参数定义

pg_pitr 参数还有更多可用选项:

pg_pitr:                           # 定义 PITR 任务
    cluster: "some_pg_cls_name"    # 源集群名称
    type: latest                   # 恢复目标类型:time, xid, name, lsn, immediate, latest
    time: "2025-01-01 10:00:00+00" # 恢复目标:时间,与 xid, name, lsn 互斥
    name: "some_restore_point"     # 恢复目标:命名恢复点,与 time, xid, lsn 互斥
    xid:  "100000"                 # 恢复目标:事务 ID,与 time, name, lsn 互斥
    lsn:  "0/3000000"              # 恢复目标:日志序列号,与 time, name, xid 互斥
    timeline: latest               # 目标时间线,可以是整数,默认为 latest
    exclusive: false               # 是否排除目标点,默认为 false
    action: pause                  # 恢复后操作:pause, promote, shutdown
    archive: false                 # 是否保留归档设置?默认为 false
    db_exclude: [ template0, template1 ]
    db_include: []
    link_map:
      pg_wal: '/data/wal'
      pg_xact: '/data/pg_xact'
    process: 4                     # 并行恢复进程数
    repo: {}                       # 恢复来源仓库
    data: /pg/data                 # 数据恢复位置
    port: 5432                     # 恢复实例的监听端口

6 - 手工恢复

在沙箱环境中按照提示脚本手动执行 PITR

您可以使用 pgsql-pitr.yml 剧本执行 PITR,但在某些情况下,您可能希望手动执行 PITR,直接使用 pgbackrest 原语实现精细的控制。 我们将使用带有 MinIO 备份仓库的四节点沙箱集群来演示该过程。


初始化沙箱

使用 vagrantterraform 准备四节点沙箱环境,然后:

curl https://repo.pigsty.io/get | bash; cd ~/pigsty/
./configure -c full
./install

现在以管理节点上的管理员用户(或 dbsu)身份操作。

pigsty-sandbox.jpg


检查备份

要检查备份状态,您需要切换到 postgres 用户并使用 pb 命令:

sudo su - postgres    # 切换到 dbsu: postgres 用户
pb info               # 打印 pgbackrest 备份信息

pbpgbackrest 的别名,会自动从 pgbackrest 配置中获取 stanza 名称。

function pb() {
    local stanza=$(grep -o '\[[^][]*]' /etc/pgbackrest/pgbackrest.conf | head -n1 | sed 's/.*\[\([^]]*\)].*/\1/')
    pgbackrest --stanza=$stanza $@
}

您可以看到初始备份信息,这是一个全量备份:

root@pg-meta-1:~# pb info
stanza: pg-meta
    status: ok
    cipher: aes-256-cbc

    db (current)
        wal archive min/max (17): 000000010000000000000001/000000010000000000000007

        full backup: 20250713-022731F
            timestamp start/stop: 2025-07-13 02:27:31+00 / 2025-07-13 02:27:33+00
            wal start/stop: 000000010000000000000004 / 000000010000000000000004
            database size: 44MB, database backup size: 44MB
            repo1: backup size: 8.4MB

备份完成于 2025-07-13 02:27:33+00,这是您可以恢复到的最早时间。 由于 WAL 归档处于活动状态,您可以恢复到备份之后的任何时间点,直到 WAL 结束(即现在)。


生成心跳

您可以生成一些心跳来模拟工作负载。/pg-bin/pg-heartbeat 就是用于此目的的, 它每秒向 monitor.heartbeat 表写入一个心跳时间戳。

make rh     # 运行心跳: ssh 10.10.10.10 'sudo -iu postgres /pg/bin/pg-heartbeat'
ssh 10.10.10.10 'sudo -iu postgres /pg/bin/pg-heartbeat'
   cls   |              ts               |    lsn     |  lsn_int  | txid | status  |       now       |  elapse
---------+-------------------------------+------------+-----------+------+---------+-----------------+----------
 pg-meta | 2025-07-13 03:01:20.318234+00 | 0/115BF5C0 | 291239360 | 4812 | leading | 03:01:20.318234 | 00:00:00

您甚至可以向集群添加更多工作负载,让我们使用 pgbench 生成一些随机写入:

make ri     # 初始化 pgbench
make rw     # 运行 pgbench 读写工作负载
pgbench -is10 postgres://dbuser_meta:DBUser.Meta@10.10.10.10:5433/meta
while true; do pgbench -nv -P1 -c4 --rate=64 -T10 postgres://dbuser_meta:DBUser.Meta@10.10.10.10:5433/meta; done
while true; do pgbench -nv -P1 -c4 --rate=64 -T10 postgres://dbuser_meta:DBUser.Meta@10.10.10.10:5433/meta; done
pgbench (17.5 (Homebrew), server 17.4 (Ubuntu 17.4-1.pgdg24.04+2))
progress: 1.0 s, 60.9 tps, lat 7.295 ms stddev 4.219, 0 failed, lag 1.818 ms
progress: 2.0 s, 69.1 tps, lat 6.296 ms stddev 1.983, 0 failed, lag 1.397 ms
...

PITR 手册

现在让我们选择一个恢复时间点,比如 2025-07-13 03:03:03+00,这是初始备份(和心跳)之后的一个时间点。 要执行手动 PITR,使用 pg-pitr 工具:

$ pg-pitr -t "2025-07-13 03:03:00+00"

它会为您生成执行恢复的指令,通常需要四个步骤:

Perform time PITR on pg-meta
[1. Stop PostgreSQL] ===========================================
   1.1 Pause Patroni (if there are any replicas)
       $ pg pause <cls>  # 暂停 patroni 自动故障切换
   1.2 Shutdown Patroni
       $ pt-stop         # sudo systemctl stop patroni
   1.3 Shutdown Postgres
       $ pg-stop         # pg_ctl -D /pg/data stop -m fast

[2. Perform PITR] ===========================================
   2.1 Restore Backup
       $ pgbackrest --stanza=pg-meta --type=time --target='2025-07-13 03:03:00+00' restore
   2.2 Start PG to Replay WAL
       $ pg-start        # pg_ctl -D /pg/data start
   2.3 Validate and Promote
     - If database content is ok, promote it to finish recovery, otherwise goto 2.1
       $ pg-promote      # pg_ctl -D /pg/data promote
[3. Restore Primary] ===========================================
   3.1 Enable Archive Mode (Restart Required)
       $ psql -c 'ALTER SYSTEM SET archive_mode = on;'
   3.1 Restart Postgres to Apply Changes
       $ pg-restart      # pg_ctl -D /pg/data restart
   3.3 Restart Patroni
       $ pt-restart      # sudo systemctl restart patroni

[4. Restore Cluster] ===========================================
   4.1 Re-Init All [**REPLICAS**] (if any)
       - 4.1.1 option 1: restore replicas with same pgbackrest cmd (require central backup repo)
           $ pgbackrest --stanza=pg-meta --type=time --target='2025-07-13 03:03:00+00' restore
       - 4.1.2 option 2: nuke the replica data dir and restart patroni (may take long time to restore)
           $ rm -rf /pg/data/*; pt-restart
       - 4.1.3 option 3: reinit with patroni, which may fail if primary lsn < replica lsn
           $ pg reinit pg-meta
   4.2 Resume Patroni
       $ pg resume pg-meta
   4.3 Full Backup (optional)
       $ pg-backup full      # 建议在 PITR 后执行新的全量备份

单节点示例

让我们从简单的单节点 pg-meta 集群开始,作为一个更简单的示例。

关闭数据库

pt-stop         # sudo systemctl stop patroni,关闭 patroni(和 postgres)
# 可选,因为如果 patroni 未暂停,postgres 会被 patroni 关闭
$ pg_stop        # pg_ctl -D /pg/data stop -m fast,关闭 postgres

pg_ctl: PID file "/pg/data/postmaster.pid" does not exist
Is server running?

$ pg-ps           # 打印 postgres 相关进程

 UID         PID   PPID  C STIME TTY      STAT   TIME CMD
postgres  31048      1  0 02:27 ?        Ssl    0:19 /usr/sbin/pgbouncer /etc/pgbouncer/pgbouncer.ini
postgres  32026      1  0 02:28 ?        Ssl    0:03 /usr/bin/pg_exporter ...
postgres  35510  35480  0 03:01 pts/2    S+     0:00 /bin/bash /pg/bin/pg-heartbeat

确保本地 postgres 没有运行,然后执行手册中给出的恢复命令:

恢复备份

pgbackrest --stanza=pg-meta --type=time --target='2025-07-13 03:03:00+00' restore
postgres@pg-meta-1:~$ pgbackrest --stanza=pg-meta --type=time --target='2025-07-13 03:03:00+00' restore
2025-07-13 03:17:07.443 P00   INFO: restore command begin 2.54.2: ...
2025-07-13 03:17:07.470 P00   INFO: repo1: restore backup set 20250713-022731F, recovery will start at 2025-07-13 02:27:31
2025-07-13 03:17:07.471 P00   INFO: remove invalid files/links/paths from '/pg/data'
2025-07-13 03:17:08.523 P00   INFO: write updated /pg/data/postgresql.auto.conf
2025-07-13 03:17:08.527 P00   INFO: restore size = 44MB, file total = 1436
2025-07-13 03:17:08.527 P00   INFO: restore command end: completed successfully (1087ms)

验证数据

我们不希望 patroni HA 接管,直到确定数据正确,所以手动启动 postgres:

pg-start
waiting for server to start....2025-07-13 03:19:33.133 UTC [39294] LOG:  redirecting log output to logging collector process
2025-07-13 03:19:33.133 UTC [39294] HINT:  Future log output will appear in directory "/pg/log/postgres".
 done
server started

现在您可以检查数据,看看是否处于您想要的时间点。 您可以通过检查业务表中的最新时间戳来验证,或者在本例中通过心跳表检查。

postgres@pg-meta-1:~$ psql -c 'table monitor.heartbeat'
   id    |              ts               |    lsn    | txid
---------+-------------------------------+-----------+------
 pg-meta | 2025-07-13 03:02:59.214104+00 | 302005504 | 4912

时间戳正好在我们指定的时间点之前!(2025-07-13 03:03:00+00)。 如果这不是您想要的时间点,可以使用不同的时间点重复恢复。 由于恢复是以增量和并行方式执行的,速度非常快。 可以重试直到找到正确的时间点。

提升主库

恢复后的 postgres 集群处于 recovery 模式,因此在提升为主库之前会拒绝任何写操作。 这些恢复参数是由 pgBackRest 在配置文件中生成的。

postgres@pg-meta-1:~$ cat /pg/data/postgresql.auto.conf
# Do not edit this file or use ALTER SYSTEM manually!
# It is managed by Pigsty & Ansible automatically!

# Recovery settings generated by pgBackRest restore on 2025-07-13 03:17:08
archive_mode = 'off'
restore_command = 'pgbackrest --stanza=pg-meta archive-get %f "%p"'
recovery_target_time = '2025-07-13 03:03:00+00'

如果数据正确,您可以提升它为主库,将其标记为新的领导者并准备接受写入。

pg-promote
waiting for server to promote.... done
server promoted
psql -c 'SELECT pg_is_in_recovery()'   # 'f' 表示已提升为主库
 pg_is_in_recovery
-------------------
 f
(1 row)

恢复集群

最后,不仅需要恢复数据,还需要恢复集群状态,例如:

  • patroni 接管
  • 归档模式
  • 备份集
  • 从库

Patroni 接管

您的 postgres 是直接启动的,要恢复 HA 接管,您需要启动 patroni 服务:

pt-start   # sudo systemctl start patroni
pg resume pg-meta      # 恢复 patroni 自动故障切换(如果之前暂停过)

归档模式

archive_mode 在恢复期间被 pgbackrest 禁用。 如果您希望新领导者的写入归档到备份仓库,还需要启用 archive_mode 配置。

psql -c 'show archive_mode'

 archive_mode
--------------
 off
psql -c 'ALTER SYSTEM RESET archive_mode;'
psql -c 'SELECT pg_reload_conf();'
psql -c 'show archive_mode'
# 您也可以直接编辑 postgresql.auto.conf 并使用 pg_ctl 重载
sed -i '/archive_mode/d' /pg/data/postgresql.auto.conf
pg_ctl -D /pg/data reload

备份集

通常建议在 PITR 后执行新的全量备份,但这是可选的。

从库

如果您的 postgres 集群有从库,您也需要在每个从库上执行 PITR。 或者,更简单的方法是删除从库数据目录并重启 patroni,这将从主库重新初始化从库。 我们将在下一个多节点集群示例中介绍这种情况。


多节点示例

现在让我们以三节点 pg-test 集群作为 PITR 示例。