2025年9月25日: PostgreSQL 18 发布!
支持的版本: 当前 (18) / 17 / 16 / 15 / 14 / 13
开发版本: devel
不支持的版本: 12 / 11 / 10 / 9.6 / 9.5

pg_rewind

pg_rewind — 将一个 PostgreSQL 数据目录与另一个从它分叉出来的数据目录同步

概要

pg_rewind [选项...] { -D | --target-pgdata } 目录 { --source-pgdata=目录 | --source-server=连接字符串 }

描述

pg_rewind 是一个用于在 PostgreSQL 集群的逻辑时间线(timeline)发生分叉后,将一个 PostgreSQL 集群与同一个集群的另一个副本进行同步的工具。一个典型的场景是在主备切换后,将旧的主服务器重新上线,使其成为跟随新主服务器的备服务器。

成功执行 rewind 操作后,目标数据目录的状态类似于源数据目录的基础备份。与执行新的基础备份或使用 rsync 等工具不同,pg_rewind 不需要比较或复制集群中未更改的关联块。它只复制现有关联文件中已更改的块;所有其他文件,包括新的关联文件、配置文件和 WAL 段,都会被完整复制。因此,当数据库很大而集群之间只有一小部分块不同时,rewind 操作会比其他方法快得多。

pg_rewind 会检查源集群和目标集群的时间线历史,以确定它们分叉的点,并期望在目标集群的 pg_wal 目录中找到一直追溯到分叉点的 WAL。分叉点可能位于目标时间线、源时间线或它们的共同祖先上。在典型的切换场景中,目标集群在分叉后很快关闭,这不是问题。但如果目标集群在分叉后运行了很长时间,其旧的 WAL 文件可能已不再存在。在这种情况下,您可以手动将它们从 WAL 归档复制到 pg_wal 目录,或者运行带有 -c 选项的 pg_rewind 来自动从 WAL 归档检索它们。pg_rewind 的使用不限于切换场景,例如,可以将备服务器提升为主服务器,运行一些写事务,然后再进行 rewind 操作使其重新成为备服务器。

运行 pg_rewind 后,需要完成 WAL 重放(replay),数据目录才能处于一致状态。当目标服务器再次启动时,它将进入归档恢复(archive recovery)模式,并重放从分叉点之前最后一个检查点开始由源服务器生成的全部 WAL。如果在运行 pg_rewind 时源服务器上的一些 WAL 已不再可用,因此无法被 pg_rewind 会话复制,那么在目标服务器启动时必须提供这些 WAL。这可以通过在目标数据目录中创建 recovery.signal 文件,并在 postgresql.conf 中配置合适的 restore_command 来实现。

pg_rewind 要求目标服务器的 postgresql.conf 中启用 wal_log_hints 选项,或者在初始化集群时启用了数据校验和(data checksums)。这两个选项目前默认都未开启。full_page_writes 也必须设置为 on,但它默认是启用的。

警告:Rewind 过程中的故障

如果在处理过程中 pg_rewind 发生故障,则目标数据文件夹可能处于无法恢复的状态。在这种情况下,建议执行一个新的全新备份。

由于 pg_rewind 会完整地复制源服务器的配置文件,因此在重启目标服务器之前,可能需要纠正用于恢复的配置,特别是如果目标服务器将重新作为源服务器的备服务器。如果在 rewind 操作完成后重启服务器,但未配置恢复,目标服务器可能会再次与主服务器分叉。

pg_rewind 会立即失败,如果它发现无法直接写入的文件。这可能发生在源服务器和目标服务器使用相同的读取-写入 SSL 密钥和证书文件映射时。如果目标服务器存在此类文件,建议在运行 pg_rewind 之前将其删除。执行 rewind 后,其中一些文件可能已从源服务器复制过来,在这种情况下,可能需要删除复制的数据,并恢复 rewind 前使用的链接集。

选项

pg_rewind 接受以下命令行参数

-D 目录
--target-pgdata=目录

此选项指定了与源同步的目标数据目录。运行 pg_rewind 之前,目标服务器必须已干净关闭。

--source-pgdata=目录

指定源服务器数据目录的文件系统路径,用于与目标服务器同步。此选项要求源服务器已干净关闭。

--source-server=连接字符串

指定一个 libpq 连接字符串,用于连接到源 PostgreSQL 服务器以与目标服务器进行同步。连接必须是正常的(非复制)连接,且使用的角色拥有足够的权限在源服务器上执行 pg_rewind 所使用的函数(参见“注意事项”部分获取详细信息),或者是一个超级用户角色。此选项要求源服务器正在运行并接受连接。

-R
--write-recovery-conf

在输出目录中创建 standby.signal 文件,并将连接设置追加到 postgresql.auto.conf 文件中。仅当在连接字符串或 环境变量 中明确指定了 dbname 时,才会记录 dbname--source-server 选项与此选项一起使用是必需的。

-n
--dry-run

执行除实际修改目标目录之外的所有操作。

-N
--no-sync

默认情况下,pg_rewind 会等待所有文件安全写入磁盘。此选项会导致 pg_rewind 在不等待的情况下返回,这样更快,但这意味着后续的操作系统崩溃可能会导致数据目录损坏。通常,此选项对于测试很有用,但不应在生产环境中使用。

-P
--progress

启用进度报告。启用此选项后,在从源集群复制数据时将显示近似的进度报告。

-c
--restore-target-wal

使用目标集群配置中定义的 restore_command 从 WAL 归档中检索 WAL 文件,前提是这些文件在 pg_wal 目录中不再可用。

--config-file=文件名

使用指定的服务器主配置文件作为目标集群的配置文件。当 pg_rewind 在此集群上内部使用 postgres 命令执行 rewind 操作时(当使用 -c/--restore-target-wal 选项检索 restore_command 以及强制完成崩溃恢复时),此选项会产生影响。

--debug

打印详细的调试输出,这主要对调试 pg_rewind 的开发者有用。

--no-ensure-shutdown

pg_rewind 要求在 rewind 之前目标服务器必须干净关闭。默认情况下,如果目标服务器没有干净关闭,pg_rewind 会以单用户模式启动目标服务器以先完成崩溃恢复,然后停止它。通过传递此选项,pg_rewind 将跳过此步骤,并在服务器未干净关闭时立即报错。在这种情况下,用户需要自行处理。

--sync-method=method

当设置为 fsync(默认值)时,pg_rewind 会递归打开并同步数据目录中的所有文件。文件搜索将遵循 WAL 目录和每个已配置表空间(tablespace)的符号链接。

在 Linux 上,还可以使用 syncfs 来要求操作系统同步包含数据目录、WAL 文件和每个表空间的整个文件系统。有关使用 syncfs 时需要注意的注意事项,请参阅 recovery_init_sync_method

当使用 --no-sync 时,此选项无效。

-V
--version

显示版本信息,然后退出。

-?
--help

显示帮助信息,然后退出。

环境变量

当使用 --source-server 选项时,pg_rewind 还会使用 libpq 支持的环境变量(参见 第 32.15 节)。

环境变量 PG_COLOR 指定是否在诊断消息中使用颜色。可能的值为 alwaysautonever

注释

当使用在线集群作为源执行 pg_rewind 时,可以使用一个具有足够权限在源集群上执行 pg_rewind 所需函数的角色,而不是超级用户。下面是创建一个名为 rewind_user 的角色的方法。

CREATE USER rewind_user LOGIN;
GRANT EXECUTE ON function pg_catalog.pg_ls_dir(text, boolean, boolean) TO rewind_user;
GRANT EXECUTE ON function pg_catalog.pg_stat_file(text, boolean) TO rewind_user;
GRANT EXECUTE ON function pg_catalog.pg_read_binary_file(text) TO rewind_user;
GRANT EXECUTE ON function pg_catalog.pg_read_binary_file(text, bigint, bigint, boolean) TO rewind_user;

工作原理

基本思想是将所有文件系统级别的更改从源集群复制到目标集群。

  1. 扫描目标集群的 WAL 日志,从源集群时间线历史分叉之前的最后一个检查点开始。对于每个 WAL 记录,记录被触及的每个数据块。这将生成一个列表,包含在源集群分叉后目标集群中更改的所有数据块。如果一些 WAL 文件不再可用,尝试使用 -c 选项重新运行 pg_rewind 来在 WAL 归档中搜索丢失的文件。

  2. 将所有这些更改过的块从源集群复制到目标集群,可以通过直接文件系统访问(--source-pgdata)或 SQL(--source-server)来实现。现在,关联文件将处于一个状态,该状态等同于源集群和目标集群 WAL 时间线分叉之前的最后一个已完成检查点时刻,再加上该分叉点之后在目标集群上发生的任何块更改的源集群当前状态。

  3. 复制所有其他文件,包括新的关联文件、WAL 段、pg_xact 和配置文件,从源集群到目标集群。与基础备份类似,来自源集群的数据复制中会省略 pg_dynshmem/pg_notify/pg_replslot/pg_serial/pg_snapshots/pg_stat_tmp/pg_subtrans/ 目录的内容。文件 backup_labeltablespace_mappg_internal.initpostmaster.optspostmaster.pid.DS_Store,以及任何以 pgsql_tmp 开头的文件或目录,都会被省略。

  4. 创建一个 backup_label 文件,以便在切换(failover)时创建的检查点开始 WAL 重放,并配置 pg_control 文件,将其最小一致性 LSN(Log Sequence Number)设置为从活动源 rewind 时 pg_current_wal_insert_lsn() 的结果,或从已停止源 rewind 时最后一个检查点 LSN。

  5. 在启动目标服务器时,PostgreSQL 会重放所有必需的 WAL,从而使数据目录处于一致状态。

提交更正

如果您在文档中发现任何不正确、与您的使用经验不符或需要进一步解释的内容,请使用 此表单 来报告文档问题。