pg_rewind
pg_rewind — 将一个 PostgreSQL 数据目录与另一个从其分叉而来的数据目录同步
大纲
pg_rewind [option...] { -D | --target-pgdata } directory { --source-pgdata= | directory--source-server= } connstr
描述
pg_rewind 是一个工具,用于在同一 PostgreSQL 集簇的两份副本时间线发生分叉后,将其中一份重新同步到另一份。典型场景是故障切换后,让旧主库重新上线,作为跟随新主库的备库。
其结果相当于用源数据目录替换目标数据目录。对于关系文件,只复制发生变化的块;其他所有文件(包括配置文件)都整体复制。pg_rewind 相较于获取新的基础备份或使用 rsync 等工具,其优势在于 pg_rewind 无需通读集簇中未发生变化的块。当数据库很大而两个集簇之间只有少量块不同时,这使它快得多。
pg_rewind 会检查源集簇和目标集簇的时间线历史,以确定它们发生分叉的位置,并且要求在目标集簇的 pg_wal 目录中能够找到一直追溯到该分叉点的 WAL。分叉点可能位于目标时间线、源时间线,或者二者共同的祖先时间线上。在典型的故障切换场景中,目标集簇会在分叉后不久关闭,因此这通常不是问题;但如果目标集簇在分叉后又运行了很长时间,旧的 WAL 文件可能已经不存在。在这种情况下,你可以手动把它们从 WAL 归档复制到 pg_wal 目录。pg_rewind 的用途并不限于故障切换,例如,备库可以被提升,运行一些写事务,然后再回卷,重新成为备库。
运行 pg_rewind 之后首次启动目标服务器时,它会进入恢复模式,并重放源服务器在分叉点之后生成的全部 WAL。如果运行 pg_rewind 时,源服务器上的某些 WAL 已经不可用,因此无法由 pg_rewind 会话复制,那么在启动目标服务器时必须能够获取这些 WAL。这可以通过在目标数据目录中创建 recovery.conf 文件,并在其中设置合适的 restore_command 来实现。
pg_rewind 要求目标服务器满足以下条件之一:要么在 postgresql.conf 中启用了 wal_log_hints 选项,要么在用 initdb 初始化集簇时启用了数据校验和(默认即如此)。此外,full_page_writes 也必须设置为 on,不过它默认已启用。
警告
如果 pg_rewind 在处理过程中失败,目标数据目录很可能已经处于无法恢复的状态。在这种情况下,建议重新获取一份全新的备份。
如果 pg_rewind 发现某些文件无法直接写入,它就会立即失败。例如,当源服务器和目标服务器对只读 SSL 密钥和证书使用相同的文件映射时,就会发生这种情况。如果目标服务器上存在这类文件,建议在运行 pg_rewind 之前将其移除。回卷完成后,其中一些文件可能已经从源复制过来,这种情况下可能需要删除复制过来的数据,并恢复回卷前使用的那组链接。
选项
pg_rewind 接受以下命令行参数:
-Ddirectory--target-pgdata=directory此选项指定要与源同步的目标数据目录。在运行 pg_rewind 之前,目标服务器必须已正常关闭。
--source-pgdata=directory指定源服务器数据目录的文件系统路径,以便将目标与之同步。此选项要求源服务器已正常关闭。
--source-server=connstr指定一个 libpq 连接字符串,用于连接源 PostgreSQL 服务器,以便将目标与之同步。该连接必须是具有超级用户权限的普通连接(非复制连接)。此选项要求源服务器正在运行且不处于恢复模式。
-n--dry-run执行除实际修改目标目录之外的所有操作。
-P--progress启用进度报告。打开该选项后,在从源集簇复制数据时会给出大致的进度信息。
--debug打印详细的调试输出,这些输出主要对调试 pg_rewind 的开发人员有用。
-V--version显示版本信息,然后退出。
-?--help显示帮助,然后退出。
环境
在使用 --source-server 选项时,pg_rewind 也会使用 libpq 支持的环境变量(见第 33.14 节)。
注解
使用最近刚提升的在线集簇作为源来执行 pg_rewind 时,必须在提升后执行 CHECKPOINT,使其控制文件反映最新的时间线信息。pg_rewind 会使用这些信息检查能否利用指定的源集簇回卷目标集簇。
工作原理
基本思路是将源集簇中所有文件系统级别的更改复制到目标集簇:
从源集簇的时间线历史与目标集簇分叉这一点之前的最后一个检查点开始,扫描目标集簇的 WAL 日志。对于每条 WAL 记录,记录它所触及的每个数据块。这样就能得到一份列表,其中包含源集簇分叉出去之后,目标集簇中所有发生过更改的数据块。
将所有这些发生过更改的块从源集簇复制到目标集簇,可以使用直接文件系统访问(
--source-pgdata)或 SQL(--source-server)。将所有其他文件,例如
pg_xact和配置文件,从源集簇复制到目标集簇(关系文件除外)。从故障切换时创建的检查点开始,应用源集簇的 WAL。(严格来说,pg_rewind 并不应用 WAL,它只是创建一个备份标签文件,让 PostgreSQL 在启动时重放从该检查点起的全部 WAL。)