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

返回本页常规视图.

时间点恢复

Pigsty 使用 pgBackRest 实现了 PostgreSQL 时间点恢复,允许用户回滚至备份策略容许范围内的任意时间点。

当您不小心删除了数据、表、甚至整个数据库时,PITR 能力让您回到过去任意时刻,避免软件缺陷与人为失误导致的数据损失。

—— 这个曾经只有资深 DBA 才能施展的『魔法』,现在对所有用户都可以轻松做到零配置开箱即用。


概览

Pigsty 的 PostgreSQL 集群带有自动配置的时间点恢复(PITR)方案,基于 pgBackRest 与可选的对象存储仓库 MinIO 提供。

高可用方案 可以解决硬件故障,但却对软件缺陷与人为失误导致的数据删除/覆盖写入/删库等问题却无能为力。 对于这种情况,Pigsty 提供了开箱即用的 时间点恢复(Point in Time Recovery, PITR)能力,无需额外配置即默认启用。

Pigsty 为您提供了基础备份与 WAL 归档的默认配置,您可以使用本地目录与磁盘,亦或专用的 MinIO 集群或 S3 对象存储服务来存储备份并实现异地容灾。 当您使用本地磁盘时,默认保留恢复至过去一天内的任意时间点的能力。当您使用 MinIO 或 S3 时,默认保留恢复至过去一周内的任意时间点的能力。 只要存储空间管够,您尽可保留任意长地可恢复时间段,丰俭由人。


时间点恢复解决什么问题?

  • 容灾能⼒增强:RPO 从 ∞ 降⾄ ⼗⼏MB, RTO 从 ∞ 降⾄ ⼏⼩时/⼏刻钟。
  • 确保数据安全:C/I/A 中的 数据完整性:避免误删导致的数据⼀致性问题。
  • 确保数据安全:C/I/A 中的 数据可⽤性:提供对“永久不可⽤”这种灾难情况的兜底
单实例配置策略事件RTORPO
什么也不做宕机 永久丢失 全部丢失
基础备份宕机 取决于备份大小与带宽(几小时) 丢失上一次备份后的数据(几个小时到几天)
基础备份 + WAL归档宕机 取决于备份大小与带宽(几小时) 丢失最后尚未归档的数据(几十MB)

时间点恢复有什么代价?

  • 降低数据安全中的 C:机密性,产生额外泄漏点,需要额外对备份进⾏保护。
  • 额外的资源消耗:本地存储或⽹络流量 / 带宽开销,通常并不是⼀个问题。
  • 复杂度代价升⾼:⽤户需要付出备份管理成本。

时间点恢复的局限性

如果只有 PITR 用于故障恢复,则 RTO 与 RPO 指标相比 高可用方案 更为逊色,通常应两者组合使用。

  • RTO:如果只有单机 + PITR,恢复时长取决于备份大小与网络/磁盘带宽,从十几分钟到几小时,几天不等。
  • RPO:如果只有单机 + PITR,宕机时可能丢失少量数据,一个或几个 WAL 日志段文件可能尚未归档,损失 16 MB 到⼏⼗ MB 不等的数据。

除了 PITR 之外,您还可以在 Pigsty 中使用 延迟集群 来解决人为失误或软件缺陷导致的数据误删误改问题。


原理

时间点恢复允许您将集群恢复回滚至过去的“任意时刻”,避免软件缺陷与人为失误导致的数据损失。要做到这一点,首先需要做好两样准备工作:基础备份WAL归档。 拥有 基础备份,允许用户将数据库恢复至备份时的状态,而同时拥有从某个基础备份开始的 WAL归档,允许用户将数据库恢复至基础备份时刻之后的任意时间点。

详细原理,请参阅:基础备份与时间点恢复;具体操作,请参考 PGSQL管理:备份恢复

基础备份

Pigsty 使用 pgbackrest 管理 PostgreSQL 备份。pgBackRest 将在所有集群实例上初始化空仓库,但只会在集群主库上实际使用仓库。

pgBackRest 支持三种备份模式:全量备份增量备份,差异备份,其中前两者最为常用。 全量备份将对数据库集群取一个当前时刻的全量物理快照,增量备份会记录当前数据库集群与上一次全量备份之间的差异。

Pigsty 为备份提供了封装命令:/pg/bin/pg-backup [full|incr]。您可以通过 Crontab 或任何其他任务调度系统,按需定期制作基础备份。

WAL归档

Pigsty 默认在集群主库上启⽤了 WAL 归档,并使⽤ pgbackrest 命令行工具持续推送 WAL 段⽂件至备份仓库。

pgBackRest 会⾃动管理所需的 WAL ⽂件,并根据备份的保留策略及时清理过期的备份,与其对应的 WAL 归档⽂件。

如果您不需要 PITR 功能,可以通过 配置集群archive_mode: off 来关闭 WAL 归档,移除 node_crontab 来停止定期备份任务。


实现

默认情况下,Pigsty提供了两种预置 备份策略:默认使用本地文件系统备份仓库,在这种情况下每天进行一次全量备份,确保用户任何时候都能回滚至一天内的任意时间点。备选策略使用专用的 MinIO 集群或S3存储备份,每周一全备,每天一增备,默认保留两周的备份与WAL归档。

Pigsty 使用 pgBackRest 管理备份,接收 WAL 归档,执行 PITR。备份仓库可以进行灵活配置(pgbackrest_repo):默认使用主库本地文件系统(local),但也可以使用其他磁盘路径,或使用自带的可选 MinIO 服务(minio)与云上 S3 服务。

pgbackrest_enabled: true          # 在 pgsql 主机上启用 pgBackRest 吗?
pgbackrest_clean: true            # 初始化时删除 pg 备份数据?
pgbackrest_log_dir: /pg/log/pgbackrest # pgbackrest 日志目录,默认为 `/pg/log/pgbackrest`
pgbackrest_method: local          # pgbackrest 仓库方法: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             # 使用本地文件系统仓库时,最多保留 3 个完整备份,至少保留 2 个
  minio:                          # pgbackrest 的可选 minio 仓库
    type: s3                      # minio 是与 s3 兼容的,所以使用 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`
    bundle: y                     # 将小文件打包成一个文件
    cipher_type: aes-256-cbc      # 为远程备份仓库启用 AES 加密
    cipher_pass: pgBackRest       # AES 加密密码,默认为 'pgBackRest'
    retention_full_type: time     # 在 minio 仓库上按时间保留完整备份
    retention_full: 14            # 保留过去 14 天的完整备份
  # 您还可以添加其他的可选备份仓库,例如 S3,用于异地容灾

Pigsty 参数 pgbackrest_repo 中的目标仓库会被转换为 /etc/pgbackrest/pgbackrest.conf 配置文件中的仓库定义。 例如,如果您定义了一个美西区的 S3 仓库用于存储冷备份,可以使用下面的参考配置。

s3:    # ------> /etc/pgbackrest/pgbackrest.conf
  repo1-type: s3                                   # ----> repo1-type=s3
  repo1-s3-region: us-west-1                       # ----> repo1-s3-region=us-west-1
  repo1-s3-endpoint: s3-us-west-1.amazonaws.com    # ----> repo1-s3-endpoint=s3-us-west-1.amazonaws.com
  repo1-s3-key: '<your_access_key>'                # ----> repo1-s3-key=<your_access_key>
  repo1-s3-key-secret: '<your_secret_key>'         # ----> repo1-s3-key-secret=<your_secret_key>
  repo1-s3-bucket: pgsql                           # ----> repo1-s3-bucket=pgsql
  repo1-s3-uri-style: host                         # ----> repo1-s3-uri-style=host
  repo1-path: /pgbackrest                          # ----> repo1-path=/pgbackrest
  repo1-bundle: y                                  # ----> repo1-bundle=y
  repo1-cipher-type: aes-256-cbc                   # ----> repo1-cipher-type=aes-256-cbc
  repo1-cipher-pass: pgBackRest                    # ----> repo1-cipher-pass=pgBackRest
  repo1-retention-full-type: time                  # ----> repo1-retention-full-type=time
  repo1-retention-full: 90                         # ----> repo1-retention-full=90

恢复

您可以直接使用以下封装命令可以用于 PostgreSQL 数据库集群的 时间点恢复

Pigsty 默认使用增量差分并行恢复,允许您以最快速度恢复到指定时间点。

pg-pitr                                 # 恢复到WAL存档流的结束位置(例如在整个数据中心故障的情况下使用)
pg-pitr -i                              # 恢复到最近备份完成的时间(不常用)
pg-pitr --time="2022-12-30 14:44:44+08" # 恢复到指定的时间点(在删除数据库或表的情况下使用)
pg-pitr --name="my-restore-point"       # 恢复到使用 pg_create_restore_point 创建的命名恢复点
pg-pitr --lsn="0/7C82CB8" -X            # 在LSN之前立即恢复
pg-pitr --xid="1234567" -X -P           # 在指定的事务ID之前立即恢复,然后将集群直接提升为主库
pg-pitr --backup=latest                 # 恢复到最新的备份集
pg-pitr --backup=20221108-105325        # 恢复到特定备份集,备份集可以使用 pgbackrest info 列出

pg-pitr                                 # pgbackrest --stanza=pg-meta restore
pg-pitr -i                              # pgbackrest --stanza=pg-meta --type=immediate restore
pg-pitr -t "2022-12-30 14:44:44+08"     # pgbackrest --stanza=pg-meta --type=time --target="2022-12-30 14:44:44+08" restore
pg-pitr -n "my-restore-point"           # pgbackrest --stanza=pg-meta --type=name --target=my-restore-point restore
pg-pitr -b 20221108-105325F             # pgbackrest --stanza=pg-meta --type=name --set=20221230-120101F restore
pg-pitr -l "0/7C82CB8" -X               # pgbackrest --stanza=pg-meta --type=lsn --target="0/7C82CB8" --target-exclusive restore
pg-pitr -x 1234567 -X -P                # pgbackrest --stanza=pg-meta --type=xid --target="0/7C82CB8" --target-exclusive --target-action=promote restore

在执行 PITR 时,您可以使用 Pigsty 监控系统观察集群 LSN 位点状态,判断是否成功恢复到指定的时间点,事务点,LSN位点,或其他点位。

pitr

1 - 时间点恢复的工作原理

本文解释 PITR 的工作机制,帮助您建立正确的心智模型:基础备份、WAL 归档、恢复窗口与事务边界

时间点恢复(PITR)的核心原理是:基础备份 + WAL 归档 = 任意时间点恢复能力。 在 Pigsty 中,这一能力由 pgBackRest 实现,并通过 定时备份 + WAL 归档 自动运行。


三要素

要素作用Pigsty 实现
基础备份提供一致的物理快照,决定恢复起点pg-backup + pgbackrest + pg_crontab
WAL 归档记录备份后的所有变更,决定恢复路径archive_mode=on + archive_command=pgbackrest ... archive-push
恢复目标指定恢复停止位置pg_pitr 参数 / pg-pitr 脚本 / pgbackrest restore

基础备份

基础备份是数据库在某一时刻的物理快照,是 PITR 的恢复起点。Pigsty 通过 pgBackRest 生成基础备份,并提供 pg-backup 脚本封装常用操作。

备份类型

类型说明恢复开销
全量备份(Full)复制全部数据文件恢复最快,空间占用最大
差异备份(Differential)相对最近一次全量备份的变化恢复需要全量 + 差异
增量备份(Incremental)相对最近一次任意备份的变化空间最省,恢复需要完整链路

Pigsty 的默认行为

  • pg-backup 默认执行增量备份,若不存在全量备份会自动补一次全量。
  • 备份任务通过 pg_crontab 配置,写入 postgres 用户的 crontab。
  • 脚本会自动识别节点角色,只有主库实际执行,从库会直接退出。

备份频率越高,需要重放的 WAL 越少,恢复速度越快。 更多细节请参阅 备份机制备份策略


WAL 归档

WAL(Write-Ahead Log)记录了数据库的每一次变更。PITR 通过持续归档 WAL,确保能够把数据库从基础备份重放到指定时刻。

Pigsty 的归档链路

Pigsty 默认开启 WAL 归档,并将归档动作交给 pgBackRest:

  • archive_mode = on
  • archive_command = pgbackrest --stanza=<cluster> archive-push %p

pgBackRest 会持续接收 WAL 段文件,并依据保留策略自动清理过期归档。 恢复时,pgBackRest 负责通过 archive-get 拉取所需 WAL。

关键影响

  • 归档延迟会缩短恢复窗口的右边界。
  • 仓库不可用会导致归档中断,直接影响 PITR 能力。

更多细节请参阅 备份机制备份仓库


恢复目标与事务边界

PITR 的恢复目标由 PostgreSQL 的 recovery_target_* 系列参数定义,Pigsty 通过 pg_pitrpg-pitr 进行封装。

目标类型

目标类型参数说明常见场景
latest恢复到 WAL 归档流末尾机房灾难后的最新恢复
timetime恢复到指定时间点误删数据
xidxid恢复到指定事务 ID错误事务回滚
lsnlsn恢复到指定 LSN精确回退
namename恢复到命名恢复点预设检查点
immediatetype: immediate第一一致点停止最快恢复

包含与排除

恢复目标默认是包含(inclusive)的。 若要回退到目标点之前,在 pg_pitr 中设置 exclusive: true,对应 PostgreSQL 的 recovery_target_inclusive = false

事务边界

PITR 会保留目标点前的已提交事务,并回滚未提交事务。

gantt
    title 事务边界与恢复目标
    dateFormat X
    axisFormat %s
    section 事务 A
    BEGIN → COMMIT (已提交) :done, a1, 0, 2
    section 事务 B
    BEGIN → 未提交 :active, b1, 1, 4
    section 恢复
    恢复目标点 :milestone, m1, 2, 0

更多操作细节请参阅 恢复操作


恢复窗口

恢复窗口由两个边界决定:

  • 左边界:最早可用的基础备份
  • 右边界:最新已归档的 WAL

pitr-scope

窗口长短取决于备份频率、备份保留与 WAL 归档保留策略:

  • local 仓库默认保留 2 个全量备份,窗口通常为 24~48 小时
  • minio 仓库默认按时间保留 14 天备份,窗口通常为 1~2 周

具体策略配置请参阅 备份策略备份仓库


时间线

时间线(Timeline)用于区分不同历史分支。以下操作会生成新时间线:

  1. PITR 恢复
  2. 从库提升(Promote)
  3. 故障切换(Failover)
gitGraph
    commit id: "初始状态"
    commit id: "写入数据"
    commit id: "继续写入"
    branch Timeline-2
    checkout Timeline-2
    commit id: "PITR 恢复点1"
    commit id: "新写入"
    branch Timeline-3
    checkout Timeline-3
    commit id: "PITR 恢复点2"
    commit id: "继续运行"
    checkout main
    commit id: "原时间线继续"

当仓库存在多个时间线时,可通过 timeline 指定目标;Pigsty 默认使用 latest。 更多细节请参阅 恢复操作

2 - 时间点恢复的实现架构

Pigsty PITR 的实现架构:pgBackRest、备份仓库与执行机制

Pigsty 使用 pgBackRest 作为 PostgreSQL 备份与恢复引擎,提供开箱即用的时间点恢复(PITR)能力。

本文从架构层面说明:备份由谁执行、数据流向哪里、仓库如何组织、故障切换后如何保持连续性


概览

PITR 架构由三条主线构成:备份执行链路WAL 归档链路恢复执行链路

链路入口引擎终点
备份pg-backup + pg_crontabpgbackrest backup备份仓库 backup/
WAL 归档PostgreSQL archive_commandpgbackrest archive-push备份仓库 archive/
恢复pg_pitr / pg-pitr / pgsql-pitr.ymlpgbackrest restore目标数据目录

更多执行细节见 备份机制恢复操作


组件与职责

组件角色描述
PostgreSQL数据源产生数据文件与 WAL 归档流
pgBackRest备份引擎执行备份、接收/拉取 WAL、执行恢复
pg-backup备份入口Pigsty 封装脚本,执行 pgbackrest backup
pg_pitr / pg-pitr恢复入口Pigsty 封装参数/脚本,执行 pgbackrest restore
备份仓库存储后端保存 backup/archive/,支持 local / minio / s3 等仓库
pgbackrest_exporter监控输出导出备份状态指标,默认监听 9854 端口

数据流

flowchart TB
    subgraph cluster["PostgreSQL 集群"]
        direction TB
        primary["Primary<br/>PostgreSQL"]
        pb["pgBackRest"]
        cron["pg-backup / pg_crontab"]
    end
    repo["备份仓库<br/>local / minio / s3"]
    restore["恢复目标数据目录"]

    cron --> pb
    primary -->|base backup| pb
    primary -->|WAL archive| pb
    pb -->|backup/archive| repo
    repo -->|restore/archive-get| pb
    pb -->|restore| restore

要点:

  • 备份pg-backup 触发,执行 pgbackrest backup 将基础备份写入仓库。
  • 归档 由 PostgreSQL 的 archive_command 触发,持续将 WAL 段写入仓库。
  • 恢复 从仓库读取备份与 WAL,通过 pgbackrest restore 重建数据目录。

部署与角色

pgBackRest 安装在 所有 PostgreSQL 节点 上,但只有 主库 实际执行备份:

  • pg-backup 会自动检测节点角色,从库执行时直接退出。
  • 发生 故障切换 后,新主库自动接管备份与归档,备份连续性不受影响。

这使得备份链路与高可用拓扑解耦,避免因主从切换导致备份中断。


仓库与隔离

Stanza(集群标识)

pgBackRest 使用 stanza 隔离不同集群的备份,Pigsty 将其映射为 pg_cluster

备份仓库
├── pg-meta/
│   ├── backup/
│   └── archive/
└── pg-test/
    ├── backup/
    └── archive/

仓库类型

Pigsty 通过 pgbackrest_method 选择仓库,通过 pgbackrest_repo 定义仓库参数:

类型特点适用场景
local本地磁盘,恢复最快开发/测试、单机部署
minio对象存储,集中式备份生产环境、异地容灾
s3云对象存储云上部署、跨区域容灾

生产环境建议使用远程仓库(MinIO/S3),以避免主机故障导致 数据与备份同时丢失。 详见 备份仓库


配置映射

Pigsty 会将 pgbackrest_repo 定义渲染为 /etc/pgbackrest/pgbackrest.conf。 备份日志位于 /pg/log/pgbackrest/,恢复过程生成临时配置并记录恢复日志。

更多细节请参阅 备份机制


可观测性

pgbackrest_exporter 会导出备份状态指标(最近备份时间、类型、大小等),默认启用,监听端口 9854。 您可以通过 pgbackrest_exporter_enabled 控制该组件。


相关文档

3 - 时间点恢复的策略权衡

PITR 策略设计中的利弊权衡:仓库选择、空间规划与策略推荐

设计 PITR 策略时,最核心的权衡来自三个维度: 备份仓库位置恢复窗口长度恢复速度与空间成本

本文帮助您在这些维度之间做出可操作的选择。


本地 vs 远程

备份仓库的位置是 PITR 策略设计的第一步。

本地仓库

将备份存储在主库本地磁盘(pgbackrest_method = local):

优势

  • 配置简单,开箱即用
  • 恢复速度快(本地 I/O)
  • 无外部依赖

劣势

  • 无异地容灾能力,主机故障时备份可能一同丢失
  • 受限于本地磁盘容量
  • 备份与生产数据位于同一故障域

远程仓库

将备份存储到 MinIO / S3 等对象存储(pgbackrest_method = minio|s3):

优势

  • 异地容灾,备份独立于数据库主机
  • 容量几乎无限,多集群可共享
  • 可配合加密、版本控制等安全策略

劣势

  • 恢复速度受网络带宽影响
  • 依赖对象存储的可用性
  • 部署与运维成本更高

如何选择

场景推荐仓库理由
开发测试local简单够用,容灾要求低
单机生产minio / s3主机故障仍可恢复
集群生产local + minio兼顾恢复速度与异地容灾
关键业务多远程仓库多地容灾,最高保护

仓库配置细节请参阅 备份仓库


空间 vs 窗口

恢复窗口越长,所需存储空间越大。窗口长度由 备份保留策略 + WAL 归档保留 决定。

影响因素

因素影响
数据库规模决定全量备份基准空间
变更速率影响增量备份与 WAL 归档大小
备份频率频率越高,恢复越快,但空间增长更快
保留时间保留越久,恢复窗口越长,空间需求越大

直观示例

假设数据库 100GB,每天变更 10GB:

每日全量备份(保留 2 份)

pitr-space

  • 全量备份:100GB × 2 ≈ 200GB
  • WAL 归档:10GB × 2 ≈ 20GB
  • 总计:约 2~3 倍数据库空间

周全量 + 每日增量(保留 14 天)

pitr-space2

  • 全量备份:100GB × 2 ≈ 200GB
  • 增量备份:约 10GB × 12 ≈ 120GB
  • WAL 归档:10GB × 14 ≈ 140GB
  • 总计:约 4~5 倍数据库空间

空间与窗口的关系是刚性约束,无法通过配置“同时更长窗口 + 更少空间”。


策略选择

每日全量备份

最简单可靠的策略,也是 Pigsty 本地仓库的默认思路:

  • 每天一次全量备份
  • 保留 2 份备份
  • 恢复窗口约 24~48 小时

适用场景:

  • 数据库规模中小(< 500GB)
  • 备份窗口充足
  • 对存储空间不敏感

全量 + 增量备份

空间优化策略,适合大库或需要更长恢复窗口:

  • 每周一次全量备份
  • 其他日期执行增量备份
  • 保留 14 天

适用场景:

  • 数据库规模较大
  • 使用对象存储
  • 需要 1~2 周恢复窗口
flowchart TD
    A{"数据库大小<br/>< 100GB?"} -->|是| B["每日全量备份"]
    A -->|否| C{"数据库大小<br/>< 500GB?"}
    C -->|否| D["全量 + 增量备份"]
    C -->|是| E{"备份窗口<br/>充足?"}
    E -->|是| F["每日全量备份"]
    E -->|否| G["全量 + 增量备份"]

推荐配置

开发测试环境

pg_crontab:
  - '00 01 * * * /pg/bin/pg-backup full'
pgbackrest_method: local
  • 恢复窗口:24~48 小时
  • 特点:配置最简,成本最低

生产集群

pg_crontab:
  - '00 01 * * 1 /pg/bin/pg-backup full'
  - '00 01 * * 2,3,4,5,6,7 /pg/bin/pg-backup'
pgbackrest_method: minio
  • 恢复窗口:7~14 天
  • 特点:异地容灾,适合生产环境

关键业务

双仓库策略(本地 + 远程):

pgbackrest_method: local
pgbackrest_repo:
  local: { path: /pg/backup, retention_full: 2 }
  minio: { type: s3, retention_full_type: time, retention_full: 14 }
  • 本地仓库用于快速恢复
  • 远程仓库用于异地容灾

更多配置细节请参阅 备份策略备份仓库

4 - 时间点恢复的典型场景

PITR 的典型应用场景:误删数据、误删表/库、批量错误、分支恢复与机房级灾难

PITR 的价值不在于“回滚数据库”本身,而在于把不可逆的人为/软件错误变回可恢复的问题。 它覆盖的场景从“误删一张表”到“整个机房不可用”,本质上解决的是逻辑错误与灾难恢复


整体认知(Overview)

PITR 解决以下问题:

场景类型典型问题推荐策略恢复目标
误删/误更新数据(DML)DELETE/UPDATE 无条件执行,脚本误操作分支恢复优先time / xid
误删表/库/Schema(DDL)DROP TABLE/DATABASE、错误迁移分支恢复time / name
批量错误/发布事故Bug 批量污染数据,修复脚本失败分支恢复 + 验证time / xid
数据审计/问题复盘需要查看历史状态,核对差异分支恢复(只读)time / lsn
机房级灾难/全量丢失硬件故障、勒索、机房断电原地恢复或重建集群latest / time

一个简单的判断原则

  • 只要写入已经造成业务错误,就应该考虑 PITR
  • 需要在线验证或只恢复部分数据 → 分支恢复
  • 必须尽快恢复服务 → 原地恢复(可接受停机)。
flowchart TD
    A["发现问题"] --> B{"能否停机?"}
    B -->|能| C["原地恢复<br/>最短恢复路径"]
    B -->|不能| D["分支恢复<br/>先验证后切换"]
    C --> E["恢复成功后重建备份"]
    D --> F["验证/导出/切流量"]

场景详情

误删/误更新数据(DML)

典型问题

  • DELETE 缺少 WHERE
  • 错误的 UPDATE 覆盖关键字段
  • 批处理脚本逻辑错误导致脏数据扩散

处理思路

  1. 止损:暂停相关应用或写入作业,防止数据继续被污染。
  2. 定位时间点:结合日志、监控、业务反馈,确定错误发生时间。
  3. 选择策略
    • 能停机:原地恢复到错误之前
    • 不能停机:分支恢复,导出正确数据再合并回主库

恢复目标建议

  • 有明确事务:xid + exclusive: true
  • 仅知道时间:time + exclusive: true
pg_pitr: { xid: "250000", exclusive: true }
# 或
pg_pitr: { time: "2025-01-15 14:30:00+08", exclusive: true }

误删表 / 误删库(DDL)

典型问题

  • DROP TABLE / DROP DATABASE
  • 执行了错误迁移脚本
  • 清理测试数据时误删生产对象

为何推荐分支恢复

DDL 操作不可逆,原地恢复意味着全库回滚,风险高。 分支恢复可将误删对象导出并导回原库,影响最小。

推荐流程

  1. 创建分支集群并 PITR 到误删前
  2. 校验表结构/数据正确性
  3. pg_dump 导出目标对象
  4. 导回生产库
sequenceDiagram
    participant O as 原集群
    participant B as 分支集群
    O->>B: 创建分支集群
    Note over B: PITR 到误删之前
    B->>O: 导出表/库并导回
    Note over B: 验证完成后销毁分支

批量错误 / 发布事故

典型问题

  • 某次版本发布写入错误数据
  • ETL 或批处理作业造成全量污染
  • 修复脚本执行失败或影响范围不清晰

处理原则

  • 优先分支恢复:先验证恢复点,再决定是否切流量
  • 对比原库与分支库数据差异,确认影响范围

建议流程

  1. 确定错误发布的时间窗口
  2. 分支恢复到“错误发生前”
  3. 校验关键业务表
  4. 决定导回部分数据,或整体切流量

这个场景通常需要结合业务复盘,因此分支恢复更安全、更可控。


数据审计 / 问题复盘

典型问题

  • 需要查看某一时刻的数据状态
  • 排查“历史正确状态”以比对差异

推荐方式:分支恢复(只读)

优点

  • 不影响生产
  • 可多次尝试不同时间点
  • 适合审计、核对与取证
pg_pitr: { time: "2025-01-15 10:00:00+08" }  # 创建只读分支

机房级灾难 / 全量丢失

这是 PITR 的终极兜底场景。当高可用无法应对时(主从同时不可用、机房断电、勒索攻击),PITR 是最后防线。

关键前提

必须使用远程仓库(MinIO/S3)

本地仓库在主机故障时会与数据一同丢失,无法恢复。

恢复流程

  1. 准备新主机或新机房资源
  2. 还原集群配置并指向远程仓库
  3. 执行 PITR 恢复(通常 latest
  4. 验证数据后恢复服务
./pgsql-pitr.yml -l pg-meta   # 恢复到 WAL 归档末尾

原地恢复 vs 分支恢复

维度原地恢复分支恢复
是否停机需要停机无需停机
风险高(直接影响生产)低(可验证后操作)
复杂度中(需要新集群与数据导出)
推荐场景快速恢复服务、容灾误操作恢复、审计、复杂场景

对于绝大多数生产场景,分支恢复是默认推荐策略。 只有在 必须尽快恢复服务 时,才建议原地恢复。


相关文档