数据库基础体系 · 第 101/139 篇。文章以各产品官方稳定版本的公开语义为准;示例会明确引擎、事务与部署边界。
PostgreSQL 备份恢复:pg_dump、Base Backup、WAL 归档和 PITR
1. 先区分四个概念
PostgreSQL 的“备份”不是一种机制,而是几种层次不同的机制:
| 机制 | 备份对象 | 能否恢复单个数据库或表 | 能否恢复到任意时间点 | 是否依赖 WAL |
|---|---|---|---|---|
pg_dump |
数据库的逻辑对象和数据 | 可以 | 不可以 | 不依赖归档 WAL |
pg_dumpall --globals-only |
集群级角色、表空间等全局对象 | 不适用 | 不可以 | 不依赖归档 WAL |
| Base Backup | 整个 PostgreSQL 集群的数据目录 | 通常不能直接只恢复一个表 | 配合 WAL 可以 | 恢复到备份之后需要 |
| WAL 归档 | 数据变化的顺序日志 | 不能单独恢复 | 配合 Base Backup 可以 | 本身就是 WAL |
| PITR | 恢复过程和目标 | 恢复的是整个集群状态 | 可以 | 必须有 Base Backup 和连续 WAL |
这里的“集群”指一个 PostgreSQL server instance 管理的数据目录,而不是某个单独的数据库。一个 PostgreSQL 集群中可以有多个数据库;物理备份覆盖整个数据目录,逻辑备份则可以针对其中一个数据库。
最重要的关系是:
而:
pg_dump 导出的是逻辑内容,Base Backup 复制的是物理数据目录。两者解决的问题不同,不能互相替代。
2. PostgreSQL 恢复为什么依赖 WAL
2.1 WAL 的基本语义
WAL,即 Write-Ahead Logging,是 PostgreSQL 的预写式日志。其核心约束是:
在数据页被写入持久存储之前,与该数据页变化对应的 WAL 必须已经持久化。
WAL 记录通常描述页面变化、事务提交、检查点等信息。事务提交时,提交记录被写入并持久化;数据页可能仍然留在共享缓冲区中,稍后才写入数据文件。
因此,崩溃恢复可以执行:
- 从某个检查点开始读取 WAL;
- 重放已经记录的页面变化;
- 根据提交、回滚和其他控制记录恢复到一致状态;
- 丢弃未完成事务产生的效果。
WAL 的本质不是“SQL 操作日志”。它是面向物理存储恢复的内部日志,通常不能直接从 WAL 还原出一组可移植的 SQL 语句。
2.2 Checkpoint 不是备份
Checkpoint 会建立一个恢复起点:
- 将脏页逐步或集中写入数据文件;
- 在 WAL 中写入检查点记录;
- 让崩溃恢复不必从集群创建以来的第一条 WAL 开始重放。
但 checkpoint 不会:
- 复制数据目录;
- 把数据保存到独立备份介质;
- 防止磁盘损坏;
- 记录一个可以脱离原集群使用的完整副本。
因此,“最近刚做过 checkpoint”不能算作备份。
2.3 Base Backup 与 WAL 的关系
假设一次 Base Backup 的备份过程为:
备份开始:LSN 0/5000000
备份结束:LSN 0/9000000
备份目录中的数据文件来自不同时间点。某个数据页可能在备份开始前复制,另一个数据页可能在备份结束前复制。因此,Base Backup 的文件集合本身未必对应一个瞬间状态。
PostgreSQL 通过以下方式保证恢复一致性:
- Base Backup 记录备份开始位置和结束信息;
- 备份期间产生的 WAL 被保留;
- 恢复时从合适的起点开始重放 WAL;
- 重放到备份结束及之后的 WAL,使所有数据页达到一致状态。
形式化地说,设:
- :Base Backup 的文件集合;
- :备份需要的 WAL 起始位置;
- :目标恢复位置;
- :从 到 的连续 WAL。
则恢复到目标位置的必要条件近似为:
缺少任意一项都可能导致恢复失败或恢复不到目标状态。
3. pg_dump:逻辑备份
3.1 pg_dump 备份什么
pg_dump 连接到一个数据库,通过 SQL 和 PostgreSQL 协议读取数据库对象与数据,然后生成逻辑转储文件。它可以包含:
- schema;
- 表、索引、约束;
- 数据;
- 序列及其当前值;
- 函数、触发器、视图;
- 大对象;
- 权限和对象所有者信息。
它不复制 PostgreSQL 数据目录中的物理页面,也不保存足以进行崩溃恢复的 WAL。
默认情况下,pg_dump 使用一致性快照读取数据库。备份期间其他事务可以继续提交;转储看到的是一个一致的逻辑视图,而不是逐表读取时刻的混合状态。
例如,创建一个示例数据库:
CREATE DATABASE appdb;
连接后创建表和数据:
CREATE TABLE orders (
id bigint PRIMARY KEY,
customer text NOT NULL,
amount numeric(12, 2) NOT NULL,
created_at timestamptz NOT NULL DEFAULT now()
);
INSERT INTO orders (id, customer, amount)
VALUES
(1, 'alice', 100.00),
(2, 'bob', 250.50);
使用自定义格式导出:
pg_dump \
--dbname=appdb \
--format=custom \
--file=/backup/appdb.dump
--format=custom 生成 PostgreSQL 自定义归档格式,适合使用 pg_restore 选择性恢复和并行恢复。也可以使用:
pg_dump --dbname=appdb --format=directory --file=/backup/appdb.dir
目录格式将转储拆成多个文件,也支持并行恢复。
如果希望得到可读的 SQL:
pg_dump \
--dbname=appdb \
--format=plain \
--file=/backup/appdb.sql
这类文件可以检查、修改后再执行,但大型数据库恢复时通常不如自定义格式灵活。
3.2 恢复 pg_dump 转储
自定义格式通常恢复到一个已经创建的目标数据库:
createdb appdb_restore
pg_restore \
--dbname=appdb_restore \
--exit-on-error \
/backup/appdb.dump
createdb 使用的是当前连接用户。如果转储中包含原始对象所有者,而目标集群中没有对应角色,恢复可能出现:
ERROR: role "app_owner" does not exist
因此,迁移或灾备时还需要单独保存集群级对象:
pg_dumpall \
--globals-only \
> /backup/globals.sql
恢复顺序通常是:
psql --dbname=postgres --file=/backup/globals.sql
createdb appdb_restore
pg_restore --dbname=appdb_restore --exit-on-error /backup/appdb.dump
globals.sql 可能包含角色、角色成员关系和表空间定义。执行它需要足够的管理权限,并且其中的密码、超级用户属性、表空间路径等内容必须经过审查。
对于大型自定义格式转储,可以并行恢复:
pg_restore \
--dbname=appdb_restore \
--jobs=4 \
--exit-on-error \
/backup/appdb.dump
并行恢复需要目录格式或自定义格式;纯 SQL 文件不能直接交给 pg_restore --jobs。并行恢复也可能增加目标服务器的 CPU、I/O 和锁竞争,不能简单认为线程越多越快。
3.3 pg_dump 的一致性边界
pg_dump 的一致性是单个数据库、单个逻辑转储操作范围内的。它不是整个 PostgreSQL 集群的原子快照。
例如,集群中有 appdb 和 auditdb:
10:00:00 pg_dump appdb 开始
10:00:10 auditdb 中写入一条审计记录
10:00:20 pg_dump auditdb 开始
两个数据库的转储可能对应不同时间点。即使分别执行 pg_dump,也不能得到跨数据库事务的一致快照。
pg_dump 还不能恢复到“误删发生前的 10:05:00”。它只保存导出时看到的逻辑状态:
导出时状态 -> 恢复时得到该状态
它不保存:
导出之后的变化 -> 任意时间点重放
因此:
- 迁移单库:
pg_dump很合适; - 恢复单表或部分对象:
pg_dump很合适; - 整个集群磁盘损坏后恢复:需要 Base Backup 和 WAL;
- 恢复到误操作前某一秒:需要 PITR。
3.4 pg_dump 的其他边界
pg_dump 默认导出一个数据库,不包括整个集群的角色和表空间等全局对象。应根据需要配合:
pg_dumpall --globals-only
它还不是物理兼容性工具:
- 逻辑转储通常可用于同一大版本内的恢复;
- 也常用于跨大版本迁移;
- 目标版本必须能够理解源转储中使用的对象和语法;
- 源版本较新的特性可能无法恢复到较旧版本。
实际迁移前应先在目标版本上做完整恢复测试,而不是只检查转储命令是否成功。
4. Base Backup:物理基础备份
4.1 Base Backup 的定义
Base Backup 是 PostgreSQL 集群数据目录的物理副本。它通常通过 pg_basebackup 创建,也可以由其他物理备份工具实现。
物理备份包含:
- 数据库表和索引的关系文件;
- 系统目录;
pg_control;- 表空间链接或表空间内容;
- 其他数据目录文件。
它面向同一 PostgreSQL 大版本的物理恢复。不能把 PostgreSQL 15 的数据目录直接当作 PostgreSQL 16 的数据目录启动;跨大版本通常需要 pg_upgrade 或逻辑迁移。
Base Backup 覆盖的是整个集群,不是某个数据库。即使只需要恢复一个表,也不能直接把某个关系文件从备份中复制回运行中的数据库;表的数据文件还依赖系统目录、FSM、VM、索引、事务状态等整体语义。
4.2 使用 pg_basebackup
一个基础示例:
pg_basebackup \
--host=primary.example.com \
--port=5432 \
--username=backup_user \
--pgdata=/backup/base-2025-03-08 \
--format=plain \
--wal-method=stream \
--progress
参数含义:
--pgdata:备份输出目录;--format=plain:写出可直接作为数据目录使用的目录树;--wal-method=stream:通过复制协议同时传输备份期间需要的 WAL;--progress:显示进度。
执行用户需要具备复制权限,例如:
CREATE ROLE backup_user
WITH LOGIN REPLICATION PASSWORD 'change-this-password';
还必须在 pg_hba.conf 中允许复制连接,例如:
host replication backup_user 10.0.0.0/24 scram-sha-256
修改认证配置后重新加载:
SELECT pg_reload_conf();
生产环境不应把密码直接写入命令行。可以使用 .pgpass,并将权限设置为只有用户本人可读:
chmod 0600 ~/.pgpass
4.3 --wal-method=stream 与 fetch
--wal-method=stream 为 Base Backup 建立一个额外的复制连接,在备份过程中持续接收 WAL。这是通常更稳妥的选择,但会消耗一个 max_wal_senders 配置允许的发送连接。
--wal-method=fetch 则在备份结束时获取所需 WAL。它要求主库在整个备份期间保留这些 WAL;如果 WAL 已经被回收,备份会失败或不完整。因此使用 fetch 时必须保证:
- WAL 归档持续成功,或者;
- 通过其他方式确保所需 WAL 不被回收。
复制槽可以帮助保留 WAL,但复制槽只解决“主库暂不回收某些 WAL”的问题,不等于把 WAL 复制到了安全介质。复制槽对应的消费者永久故障时,主库的 pg_wal 可能不断增长并耗尽磁盘。
4.4 Base Backup 的一致性保证
pg_basebackup 不是简单的目录复制。服务器端会把备份过程纳入 PostgreSQL 的备份协议,记录备份边界,并保证恢复所需的 WAL 得以获取。
备份结束后,输出目录通常包含备份清单。可以用:
pg_verifybackup /backup/base-2025-03-08
验证 Base Backup 的文件清单和校验信息。它能发现文件缺失或内容变化,但不能证明:
- 备份介质永远不会损坏;
- WAL 归档链完整;
- 目标时间点一定存在;
- 恢复后的应用行为符合预期。
因此验证 Base Backup 后仍应执行实际启动恢复测试。
如果使用 PostgreSQL 版本支持的校验和,可以在集群级启用数据校验和;但校验和主要帮助发现页面损坏,不是备份机制,也不能替代异地副本。
5. WAL 归档
5.1 WAL 归档做什么
WAL 文件位于数据目录下的 pg_wal。服务器会循环使用已经不再需要的 WAL 段。若希望在基础备份之后恢复到更晚的状态,就必须在 WAL 被回收前把它们保存到独立位置。
WAL 归档的过程是:
事务产生 WAL
↓
WAL 写入 pg_wal
↓
一个 WAL 段完成
↓
执行 archive_command 或 archive_library
↓
归档目标保存该 WAL 段
WAL 归档保存的是完整 WAL 段文件,而不是每个事务一条独立文件。
常见配置方式:
archive_mode = on
archive_command = 'test ! -f /srv/pgarchive/%f && cp %p /srv/pgarchive/%f'
其中:
%p:源 WAL 文件的完整路径;%f:WAL 文件名;archive_command返回 0 表示归档成功;- 返回非 0 表示失败,PostgreSQL 会保留该 WAL,并在之后重试。
archive_mode 通常需要重启才能启用;修改 archive_command 本身通常可以通过配置重载生效。新版本还支持 archive_library 等归档方式,具体取决于所使用的 PostgreSQL 大版本和归档扩展。
5.2 archive_command 的正确与错误
这个命令有一个非常重要的契约:
只有在目标文件已经安全保存后,归档命令才可以返回成功。
错误示例:
archive_command = 'cp %p /some/path/; true'
如果 cp 失败而 true 仍返回 0,PostgreSQL 会认为归档成功,之后可能回收本地 WAL。这样会形成无法恢复的 WAL 缺口。
常见的本地归档写法:
archive_command = 'test -f /srv/pgarchive/%f || cp %p /srv/pgarchive/%f'
test -f 用于让重试具有幂等性:如果目标文件已经存在,就不重复覆盖。实际生产环境还应考虑:
- 目标目录位于独立磁盘或远程存储;
- 复制完成后的持久化语义;
- 网络存储暂时不可用;
- 同名文件内容不一致时必须报警,而不能静默跳过;
- 归档目录不能被备份工具随意清理。
仅有一个 cp 到同一台主机上的另一个目录,不能充分抵御主机、磁盘或存储控制器故障。
5.3 检查归档状态
可以查看归档统计:
SELECT
archived_count,
failed_count,
last_archived_wal,
last_archived_time,
last_failed_wal,
last_failed_time
FROM pg_stat_archiver;
测试归档时,可以主动切换 WAL:
SELECT pg_switch_wal();
这只会请求切换到新的 WAL 段;归档动作是异步的。随后应检查:
SELECT
last_archived_wal,
last_archived_time,
failed_count,
last_failed_wal
FROM pg_stat_archiver;
不能仅因为 pg_switch_wal() 返回了 LSN,就认为归档已经成功。
如果归档连续失败,常见现象包括:
pg_stat_archiver.failed_count增加;pg_wal中 WAL 持续增长;- 磁盘最终耗尽;
- 数据库写入因无法继续分配 WAL 而受到影响。
archive_timeout 可以在一段时间内没有写满 WAL 段时强制切换,降低低写入量系统的恢复延迟,但会产生更多未填满的 WAL 段,增加归档量。它不能修复归档失败。
6. 用 Base Backup 和 WAL 做 PITR
PITR 是 Point-in-Time Recovery,即时间点恢复。它不是单独的备份格式,而是 PostgreSQL 在启动恢复阶段:
- 载入一个 Base Backup;
- 执行
restore_command获取 WAL; - 按顺序重放 WAL;
- 在目标时间、LSN、事务 ID 或恢复名称处停止;
- 暂停、提升为新主库,或继续恢复。
6.1 先定义恢复目标
常见恢复目标有:
recovery_target_time:某个时间点;recovery_target_lsn:某个 WAL LSN;recovery_target_xid:某个事务 ID;recovery_target_name:预先创建的恢复目标名称;recovery_target='immediate':恢复到达到一致状态后尽快停止。
例如,应用在:
2025-03-08 10:15:42+08
误执行了删除操作,希望恢复到该操作之前,就应选择一个明确早于误操作提交时间的目标,而不能直接把目标时间写成“发现问题的时间”。
时间恢复的精度受 WAL 记录和事务提交记录影响。recovery_target_time 表示恢复过程要到达的时间边界;事务提交是否包含在目标状态中还受到 recovery_target_inclusive 等选项影响。生产操作不能只依赖人脑记忆的时间,最好结合应用日志、数据库审计记录和 WAL 位置确认目标。
6.2 恢复目录准备
假设:
Base Backup: /backup/base-2025-03-08
WAL 归档目录: /srv/pgarchive
目标数据目录: /var/lib/postgresql/17/main
必须先停止目标实例,然后准备一个空的数据目录:
pg_ctl -D /var/lib/postgresql/17/main stop -m fast
rm -rf /var/lib/postgresql/17/main/*
cp -a /backup/base-2025-03-08/. /var/lib/postgresql/17/main/
chown -R postgres:postgres /var/lib/postgresql/17/main
不要在运行中的 PostgreSQL 数据目录上直接覆盖文件。也不要把 Base Backup 放在源实例仍可能修改的目录中进行恢复。
在 PostgreSQL 12 及之后的版本中,恢复配置不再使用旧式独立的 recovery.conf 文件。需要在数据目录中创建 recovery.signal:
touch /var/lib/postgresql/17/main/recovery.signal
chown postgres:postgres /var/lib/postgresql/17/main/recovery.signal
然后在 postgresql.conf 中配置:
restore_command = 'cp /srv/pgarchive/%f %p'
recovery_target_time = '2025-03-08 10:15:40+08'
recovery_target_action = 'pause'
recovery_target_timeline = 'latest'
这里:
%f是 PostgreSQL 请求的 WAL 文件名;%p是目标数据目录中应写入该文件的路径;recovery_target_action=pause让服务器在达到目标后暂停,便于检查;recovery_target_timeline=latest允许恢复过程中跟随可用的最新时间线。
restore_command 找不到目标文件时必须返回非 0,例如:
test -f /srv/pgarchive/%f && cp /srv/pgarchive/%f %p
不要把“文件不存在”当作成功,否则 PostgreSQL 会误以为 WAL 已经被恢复。
启动实例:
pg_ctl \
-D /var/lib/postgresql/17/main \
-l /var/log/postgresql/pitr.log \
start
恢复期间可以观察日志:
tail -f /var/log/postgresql/pitr.log
典型流程是:
读取 Base Backup
↓
读取 backup_label 中的备份信息
↓
调用 restore_command 获取 WAL
↓
重放 WAL
↓
达到 recovery_target_time
↓
进入 paused 状态
达到目标后,可以连接检查:
SELECT pg_is_in_recovery();
结果为:
t
说明实例仍处于恢复状态。此时可以执行只读校验,例如:
SELECT count(*) FROM orders;
SELECT max(created_at) FROM orders;
确认状态后提升为独立主库:
SELECT pg_promote();
或者:
pg_ctl -D /var/lib/postgresql/17/main promote
再次检查:
SELECT pg_is_in_recovery();
结果应为:
f
提升后,数据库进入一条新的时间线。之后在该实例上继续写入,就不应再把它当作原主库的普通延续;需要按故障切换流程重新配置应用、复制和备份。
6.3 时间线为什么重要
当数据库从某个时间点恢复并开始写入时,WAL 历史会分叉:
主时间线 1: A ─ B ─ C ─ D ─ E
\
新时间线 2: C' ─ D'
时间线历史文件记录了这种分叉关系。PITR 可能需要:
- 原始时间线上的 WAL;
- 时间线历史文件;
- 目标时间线上的 WAL。
因此归档系统必须保留时间线历史文件,不能只按 WAL 段文件做简单覆盖。归档仓库还必须避免不同时间线的同名 WAL 文件互相覆盖。
恢复到错误时间点后又提升为新主库,原主库可能仍然存在。此时如果不隔离旧主库,它可能继续接受写入,形成双主写入和数据分叉。这是故障切换问题,不是 pg_promote() 能自动解决的问题。
7. 一次完整的备份恢复设计
假设目标是:
- 可以恢复整个集群;
- 可以恢复到误操作前的时间;
- 也可以单独恢复某个数据库或表;
- 备份文件存放在独立存储上。
通常至少需要以下数据流:
PostgreSQL 主库
├── pg_dump ───────────────> 逻辑备份仓库
├── pg_basebackup ─────────> Base Backup 仓库
└── WAL 归档 ──────────────> WAL 仓库
恢复路径分别是:
逻辑对象恢复:
pg_dump 文件 ──> 新数据库 ──> 选择性恢复
整库时间点恢复:
Base Backup + WAL ──> PITR ──> 新时间线上的集群
例如,某个逻辑备份在每天凌晨生成,Base Backup 每周生成,WAL 持续归档。若周三发生故障:
- 选取周日的 Base Backup;
- 从该备份要求的 WAL 起点开始,连续取得 WAL;
- 重放到周三故障前的目标时间;
- 在恢复实例上验证;
- 提升实例并切换应用。
如果周日 Base Backup 之后的某个 WAL 段缺失,即使周一到周三的其他 WAL 都存在,也不能无缝恢复越过这个缺口:
base ─ A ─ B ─ 缺失 ─ D ─ E
最多只能恢复到 B 所代表的可用位置。WAL 归档的“连续性”比“文件数量很多”更重要。
8. 常见误解与失败表现
8.1 “有了 pg_dump 就能 PITR”
不能。pg_dump 没有保存物理 WAL 链,无法将数据库状态重放到导出之后的任意时间。
8.2 “Base Backup 成功,所以一定能 PITR”
也不能。还需要:
- Base Backup 本身完整;
- 从备份所需起点到目标时间的 WAL 连续;
- 时间线历史文件可用;
restore_command能返回正确文件;- 目标时间确实位于可恢复历史中。
8.3 “复制副本就是备份”
流复制副本通常会重放主库的 WAL。主库上发生误删、错误更新或恶意操作后,副本也会重放同样的变化。
副本可以提高可用性和读取能力,但不自动提供:
- 历史版本;
- 误操作前状态;
- 长期保留;
- 独立故障域。
同步复制也不能替代备份,因为它会同步错误操作。
8.4 “复制槽可以代替 WAL 归档”
不能。复制槽主要用于阻止主库过早回收消费者尚未读取的 WAL。它不会保证 WAL 已写入远程备份仓库,也不会在主库磁盘损坏后提供独立副本。
8.5 restore_command 反复报错
需要先检查恢复日志中 PostgreSQL 请求的具体文件名,然后检查:
ls -l /srv/pgarchive/<requested-wal-file>
重点排查:
- 归档文件不存在;
- 文件权限不足;
- 归档文件损坏;
%f、%p使用错误;- 归档仓库没有时间线历史文件;
- 目标实例运行用户无法执行复制命令。
恢复命令找不到文件时返回非 0 是正常的:这可能意味着当前 WAL 尚未出现在归档仓库中,PostgreSQL 会按恢复流程重试或继续判断。真正危险的是命令在失败时返回 0。
8.6 恢复后查询结果不符合预期
首先确认:
SELECT pg_is_in_recovery();
如果仍在恢复中,可能因为:
recovery_target_action=pause;- 目标时间尚未达到;
- WAL 归档不完整;
- 恢复在等待新的 WAL;
- 选择了错误的时间线。
还应检查服务器日志中的:
- recovery start;
- requested WAL segment;
- recovery target reached;
- paused;
- promoted;
- timeline switch。
不要只根据 PostgreSQL 是否能启动判断恢复成功。启动成功只说明服务器找到了可启动的一致状态,不代表它已经恢复到业务要求的时刻。
9. 备份策略中的核心验证
备份系统至少要验证三个不同问题:
9.1 备份是否成功生成
逻辑备份应检查命令退出码、文件大小和归档内容:
pg_restore --list /backup/appdb.dump | head
如果文件为零字节或 pg_restore --list 无法读取,不能视为有效备份。
Base Backup 可以执行:
pg_verifybackup /backup/base-2025-03-08
9.2 WAL 是否连续可取
不能只看 archive_command 当前没有报错。应检查:
- 归档统计;
- 归档仓库中的 WAL 范围;
- Base Backup 对应的起始 WAL;
- 是否存在时间线历史文件;
- 归档清理任务是否删除了仍需使用的 WAL。
9.3 是否真的能恢复业务
应在隔离环境中定期执行:
- 选择一个 Base Backup;
- 恢复其文件;
- 配置
restore_command; - 恢复到指定时间;
- 查询关键表和关键业务数据;
- 执行必要的应用级校验;
- 记录从开始恢复到可用所需的时间。
恢复测试还能测出两个重要指标:
- RPO:最多丢失多少时间的数据;
- RTO:从故障开始到业务恢复需要多久。
例如,WAL 归档平均延迟 2 分钟,且最后一次成功归档发生在故障前 2 分钟,那么异步归档路径的实际 RPO 可能至少接近这段延迟;但最终 RPO 仍取决于归档是否连续、目标存储是否可用以及故障发生时 WAL 是否已经安全到达归档介质。
10. 如何选择机制
可以按恢复目标选择:
只需要迁移一个数据库
使用:
pg_dump + pg_restore
它可以选择对象、修改 schema,并适合跨大版本迁移。
需要恢复整个集群到某个时间点
使用:
Base Backup + 连续 WAL 归档 + PITR
这是 PostgreSQL 物理时间点恢复的完整链路。
需要单表恢复
通常做法是:
- 从 Base Backup 和 WAL 创建一个临时 PITR 实例;
- 在临时实例中使用
pg_dump导出目标表或目标数据库; - 将逻辑转储恢复到生产环境。
这说明逻辑备份和物理恢复并非互斥:Base Backup + WAL 负责把历史状态找回来,pg_dump 负责从该状态中提取需要的对象。
需要高可用
使用流复制、同步复制、复制槽和故障切换机制,但仍应配合独立的 Base Backup、WAL 归档和恢复测试。高可用解决“尽快切换到可用节点”,备份恢复解决“找回历史状态和应对逻辑错误”。二者的故障模型不同。
系列导航与关联阅读
- 系列入口:数据库完整学习路线:从关系模型、事务索引到分布式与向量检索
- 上一篇:PostgreSQL 逻辑复制与 CDC:Publication、Slot、顺序和 Schema
- 下一篇:PostgreSQL 监控与诊断:pg_stat、锁、膨胀、慢查询和容量
- 延伸:PostgreSQL WAL 与 Checkpoint:提交、崩溃恢复、归档和写入性能
- 延伸:PostgreSQL 复制与高可用:流复制、复制槽、PITR 和故障切换
官方资料
本文依据数据库官方文档重新梳理;正文、示例与生产检查清单由 WR BLOG 编写。

评论
0 条讨论