PITR 原理

基础备份与 WAL 归档如何协同工作,实现时间点恢复。

时间点恢复(Point-In-Time Recovery,PITR)是 PostgreSQL 的核心能力之一。它允许将数据库恢复到过去任意时刻的状态。


核心概念

基础备份(Base Backup)

基础备份是数据库数据文件的完整拷贝,包括:

  • 所有表空间的数据文件
  • 配置文件
  • 事务日志的起始位置

pgBackRest 支持三种备份类型:

类型 说明 适用场景
全量备份(full) 完整拷贝所有数据 首次备份、周期性完整备份
差异备份(diff) 自上次全量以来的变更 日常备份,恢复速度快
增量备份(incr) 自上次任意备份以来的变更 频繁备份,节省空间

WAL 归档

WAL(Write-Ahead Log)记录了数据库的所有变更操作:

  • 每个事务提交前,变更先写入 WAL
  • WAL 文件按段组织,默认每段 16MB
  • 段写满后自动归档到备份仓库
数据变更 → 写入 WAL → WAL 段写满 → 归档到备份仓库

恢复原理

PITR 恢复分为两个阶段:

阶段一:恢复基础备份

备份仓库                         目标服务器
┌──────────────┐               ┌──────────────┐
│ 基础备份      │ ───拷贝──→   │ 数据目录      │
│ (2024-01-15) │               │ /pg/data     │
└──────────────┘               └──────────────┘

从备份仓库下载并恢复基础备份到目标数据目录。

阶段二:重放 WAL

备份仓库                         目标服务器
┌──────────────┐               ┌──────────────┐
│ WAL 归档      │               │ PostgreSQL   │
│ 00000001...  │ ───重放──→   │ 恢复进程     │
│ 00000001...  │               │              │
│ 00000001...  │               │ 停止于目标时间 │
└──────────────┘               └──────────────┘

PostgreSQL 恢复进程从归档中读取 WAL,按顺序重放变更,直到:

  • 达到指定的目标时间点
  • 达到指定的事务 ID
  • 达到指定的 LSN 位置
  • 重放完所有可用的 WAL

恢复目标

pgBackRest 支持多种恢复目标类型:

目标类型 参数 说明
时间 --target-time 恢复到指定时间点
事务 ID --target-xid 恢复到指定事务
LSN --target-lsn 恢复到指定日志位置
命名点 --target-name 恢复到命名的恢复点
立即 --target-action=promote 恢复到最新可用状态

恢复时间线

每次 PITR 恢复都会创建新的时间线(Timeline):

Timeline 1: ─────────────────────────────────────────────→
                              │
                         故障点(DROP TABLE)
                              │
                              ↓ PITR 恢复
Timeline 2:                   ├─────────────────────────→
                              │
                         恢复到故障前

时间线机制确保:

  • 恢复后的数据不会与原时间线混淆
  • 可以对同一基础备份进行多次恢复
  • 保留完整的历史记录

关键参数

pgBackRest 相关

参数 默认值 说明
pgbackrest_enabled true 是否启用备份
pgbackrest_method local 备份仓库类型
pgbackrest_repo - 仓库配置详情

PostgreSQL 归档相关

参数 默认值 说明
archive_mode on 启用 WAL 归档
archive_command pgbackrest 归档命令
archive_timeout 300 强制归档超时(秒)

备份链

pgBackRest 使用备份链管理多个备份之间的依赖关系:

全量备份1 ──→ 差异1 ──→ 增量1 ──→ 增量2
    │
    └────→ 差异2 ──→ 增量3

全量备份2 ──→ 差异3

恢复时需要:

  • 一个全量备份
  • 加上依赖的差异/增量备份(如有)
  • 加上对应时间段的 WAL 归档

与流复制的区别

特性 流复制(高可用) PITR(备份恢复)
目的 实时热备,故障切换 历史数据恢复
数据延迟 毫秒级 可恢复到任意历史时间
存储位置 从库本地磁盘 备份仓库(本地/远程)
恢复速度 即时切换 需要恢复过程
防护范围 硬件故障 软件缺陷、人为误操作

最佳实践:两者结合使用,互为补充。