pgBackRest 是一个功能强大、可靠且易于使用的 PostgreSQL 备份和恢复工具。它的设计目标是处理大规模数据库和高并发负载。
一、pgBackRest 核心特性
pgBackRest 的备份原理结合了 PostgreSQL 自身的物理备份机制和 WAL (Write-Ahead Log) 归档,并在此基础上增加了许多优化和管理功能。
- 并行处理 (Parallelism): 备份和恢复过程可以使用多个进程并行执行,大大缩短了大型数据库的操作时间。
- 压缩 (Compression): 支持多种压缩算法(如 gzip, lz4, zstd)来减少备份文件的大小和网络传输量。
- 校验和 (Checksums): 在备份、恢复和 WAL 归档的各个阶段都进行数据校验,确保数据完整性。默认情况下,即使 PostgreSQL 本身的 checksums 关闭,pgBackRest 也会进行校验。
- 断点续传 (Resumable Backups): 如果备份过程中断(例如网络问题),可以从中断点继续,而不是重新开始。
- 备份轮转和保留 (Retention): 可以配置策略自动删除过期的备份,以节省存储空间。支持基于数量或时间的保留策略。
- 加密 (Encryption): 支持对备份仓库中的数据进行加密。
- Delta Restore: 在恢复时,如果目标目录已存在部分未损坏的数据文件,pgBackRest 可以只恢复不同的或缺失的文件/块,加速恢复过程。
二、pgBackRest 备份前提条件
-
所有机器: 都安装了
pgBackRest
-
数据库服务器:
pg_server
(运行 PostgreSQL) -
备份仓库服务器:
repo_server
(存储备份文件) -
PostgreSQL 用户:
postgres
(拥有$PGDATA
权限) -
备份仓库用户:
pgbackrest
(拥有备份仓库目录权限) -
Stanza 名称:
mystanza
-
pgBackRest 配置:
- 在
pg_server
的pgbackrest.conf
: 配置了repo1-host=repo_server
,repo1-host-user=pgbackrest
,pg1-path=/path/to/pgdata
等。 - 在
repo_server
的pgbackrest.conf
: 配置了pg1-host=pg_server
,pg1-user=postgres
,repo1-path=/path/to/repo
等。
- 在
-
SSH 免密登录: 已配置好
pgbackrest@repo_server
可以免密登录到postgres@pg_server
,并且postgres@pg_server
可以免密登录到pgbackrest@repo_server
。 -
命令执行: 我们将在
repo_server
上以pgbackrest
用户身份执行备份命令。
三、全量备份流程 (pgbackrest --stanza=mystanza --type=full backup
)
-
启动命令 (在
repo_server
):- 在
repo_server
上以pgbackrest
用户执行pgbackrest --stanza=mystanza --type=full backup
。 - pgBackRest 进程启动,读取
repo_server
上的/etc/pgbackrest.conf
(或指定配置文件)。 - 解析命令行参数 (
--stanza
,--type
) 和配置文件,确定 Stanzamystanza
的相关信息,包括数据库服务器地址 (pg1-host=pg_server
)、用户 (pg1-user=postgres
) 和仓库路径 (repo1-path=/path/to/repo
)。
- 在
-
获取仓库锁 (在
repo_server
):- pgBackRest 尝试在备份仓库中为
mystanza
创建并锁定一个文件(例如/path/to/repo/backup/mystanza/backup.lock
)。 - 目的: 防止同一时间对同一个 Stanza 执行另一个备份或恢复操作,保证操作的原子性和一致性。如果锁定失败(文件已存在并被锁定),命令会报错退出。
- pgBackRest 尝试在备份仓库中为
-
连接数据库服务器 & 准备备份 (SSH 交互):
-
pgBackRest 在
repo_server
上的主进程需要与pg_server
上的 PostgreSQL 实例交互以开始备份。 -
SSH 命令 (概念性): 它会执行类似如下的 SSH 命令来在
pg_server
上启动一个 pgBackRestremote
进程来处理数据库端的操作:Bashssh postgres@pg_server "pgbackrest --stanza=mystanza --log-level-file=<level> --command=backup --type=db --process=1 remote"
(注意: 这只是概念性表示,实际命令和参数可能更复杂,pgBackRest 使用其内部协议进行通信)
-
pg_server
上的remote
进程:- 这个远程进程启动,读取
pg_server
上的pgbackrest.conf
以获取pg1-path
等本地信息。 - 连接到本地 PostgreSQL 实例 (使用
pg1-path
找到 socket 或通过pg1-host
/pg1-port
连接)。 - 执行
pg_start_backup('pgBackRest backup start ...')
SQL 命令(或使用流复制协议的等效命令)。 - PostgreSQL 进入备份模式,创建一个
backup_label
文件在$PGDATA
中,并返回备份的起始 LSN (Log Sequence Number)。 - 如果
start-fast=n
(默认为y
),会等待检查点完成。通常会快速继续。 remote
进程将起始 LSN 和backup_label
内容等信息通过 SSH 连接返回给repo_server
上的主进程。
- 这个远程进程启动,读取
-
-
传输数据文件 (并行的 SSH 交互):
-
repo_server
上的主进程了解到备份已在pg_server
开始。 -
它会确定需要复制的文件列表(对于
full
备份,是$PGDATA
下的所有文件,除了pg_wal
等排除项)。 -
主进程会启动多个工作 (worker) 进程 (数量由
process-max
控制) 在repo_server
上并行处理文件传输。 -
每个 worker 进程 (在
repo_server
) 会与pg_server
建立 SSH 连接来获取文件数据:-
SSH 命令 (概念性): 每个 worker 可能执行类似命令,请求特定的文件或文件块:
Bashssh postgres@pg_server "pgbackrest --stanza=mystanza --command=backup --type=file --process=<worker_id> remote --file-path=/path/to/pgdata/base/12345/67890 --compress=<type> --checksum ..."
(同样,这是概念表示。pgBackRest 可能使用更优化的流式传输协议通过 SSH 隧道)
-
pg_server
上的remote
进程 (或由主 remote 进程协调的文件服务): 读取请求的文件,进行压缩(如果配置在源端压缩)、计算校验和,然后将数据流通过 SSH 连接发送回repo_server
上的对应 worker 进程。 -
repo_server
上的 worker 进程: 接收数据流,进行解压(如果压缩在源端)、校验和验证,然后将文件写入备份仓库 (repo1-path
) 中对应的目录结构下。
-
-
这个过程会持续进行,直到所有需要备份的文件都被 worker 进程成功传输和验证。
-
-
结束数据库服务器上的备份 (SSH 交互):
-
当所有 worker 进程在
repo_server
上完成文件传输后,主进程再次通过 SSH 连接到pg_server
来结束备份模式。 -
SSH 命令 (概念性):
Bashssh postgres@pg_server "pgbackrest --stanza=mystanza --log-level-file=<level> --command=backup --type=db --action=stop --process=1 remote"
-
pg_server
上的remote
进程:- 连接到 PostgreSQL 实例。
- 执行
pg_stop_backup()
SQL 命令(或流复制协议等效命令)。 - PostgreSQL 退出备份模式,将包含结束 LSN 和其他元信息的
backup_label
文件重命名为backup_history
文件(旧机制)或完成相关记录,并返回结束 LSN、所需的最后一个 WAL 文件名等信息。 remote
进程将这些结束信息通过 SSH 返回给repo_server
上的主进程。
-
-
验证 WAL 归档 (在
repo_server
):repo_server
上的主进程现在知道了备份覆盖的 LSN 范围(从pg_start_backup
的 LSN 到pg_stop_backup
的 LSN)。- 它会检查备份仓库中的 WAL 归档目录 (
/path/to/repo/archive/mystanza
),确认从上一个备份结束到本次备份结束之间的所有必需的 WAL 文件是否都已存在。 - 重要:
backup
命令本身通常不负责 触发 WAL 的推送 (archive-push
)。它依赖于 PostgreSQL 配置的archive_command
(指向pgbackrest archive-push
) 持续不断地将 WAL 文件推送到仓库。backup
命令只是在结束时检查 这些必需的 WAL 是否已经在那里。
-
写入备份元数据 (在
repo_server
):-
pgBackRest 在备份仓库中为这次备份创建一个重要的清单文件 (manifest file) ,通常是
backup.manifest
。 -
此文件包含:
- 备份的详细信息 (类型、时间戳、LSN 范围、PostgreSQL 版本、系统标识符等)。
- 备份中包含的所有文件的列表,及其大小、修改时间、校验和等。
- 关于依赖的 WAL 段的信息。
- 表空间信息(如果有)。
-
这个文件对于后续的恢复操作至关重要。
-
-
更新备份信息和清理 (在
repo_server
):- 更新 Stanza 的全局信息文件 (例如
backup.info
),记录这次新备份的状态。 - 根据配置的保留策略 (
repo1-retention-full
,repo1-retention-diff
等),检查并删除过期的旧备份集及其相关的 WAL 文件。 - 释放仓库锁: 删除之前创建的锁文件 (
/path/to/repo/backup/mystanza/backup.lock
)。 - 备份命令执行结束,向用户报告成功或失败。
- 更新 Stanza 的全局信息文件 (例如
四、重要注意事项
-
SSH免密: 在远程仓库备份场景下,SSH 是 pgBackRest 实现服务器间协调和数据传输的主要通道
-
权限: 运行 pgBackRest 的用户(如
postgres
或pgbackrest
)需要对 PG 数据目录有读权限,对备份仓库目录有读写权限。如果使用 SSH,确保 SSH 用户有相应权限。 -
一致性: 确保
pgbackrest.conf
在所有相关服务器(PG 主库、备份服务器、可能还有备库)上保持一致(至少[global]
和 Stanza 的定义部分)。 -
用户: 推荐使用专门的
pgbackrest
用户来管理备份仓库,而不是直接使用postgres
用户,以遵循最小权限原则。 -
测试恢复: 定期测试你的备份是否可以成功恢复,这是备份策略中至关重要的一环。