pg_rewind — 把一个 PostgreSQL 数据目录与另一个从它分叉出来的数据目录同步
pg_rewind [option...] { -D | --target-pgdata } directory { --source-pgdata= | directory--source-server= } connstr
pg_rewind 是一个用于在集群的时间线发生分叉之后,把一个 PostgreSQL 集群与同一集群的另一个副本进行同步的工具。一个典型的场景是:在故障转移之后,把一台旧的主服务器作为追随新主服务器的后备重新联机。
在一次成功的回卷之后,目标数据目录的状态类似于源数据目录的一次基础备份。与进行一次新的基础备份或使用类似 rsync 的工具不同,pg_rewind 不需要比较或复制集群中未更改的关系块。只有现有关系文件中已更改的块会被复制;所有其他文件,包括新的关系文件、配置文件和 WAL 段,都会被完整复制。因此,当数据库很大而集群之间只有一小部分块不同时,回卷操作比其他方法要快得多。
pg_rewind 会检查源集群和目标集群的时间线历史,以确定两者发生分叉的位置,并且期望能在目标集群的 pg_wal 目录中找到一直回溯到分叉点的 WAL。分叉点可能位于目标时间线、源时间线或它们共同的祖先之上。在目标集群在分叉后不久即被关闭的典型故障转移场景中,这不是问题;但如果目标集群在分叉之后运行了很长时间,其旧的 WAL 文件可能已经不存在了。在这种情况下,你可以手工把它们从 WAL 归档复制到 pg_wal 目录,或者运行 pg_rewind 并带上 -c 选项来从 WAL 归档自动取回它们。pg_rewind 的使用并不限于故障转移,例如一台后备服务器可以被提升、执行一些写事务,然后再被回卷成一台后备服务器。
在运行 pg_rewind 之后,需要完成 WAL 重放,数据目录才能处于一致状态。当目标服务器再次被启动时,它将进入归档恢复,并重放源服务器中从分叉点之前最后一个检查点开始生成的所有 WAL。如果在运行 pg_rewind 时某些 WAL 在源服务器上已不再可用,因而无法由 pg_rewind 会话复制,那么在目标服务器启动时必须让这些 WAL 可用。这可以通过在目标数据目录中创建一个 recovery.signal 文件,并配置一个合适的 restore_command(在 postgresql.conf 中)来完成。
pg_rewind 要求目标服务器或者启用了 wal_log_hints 选项(在 postgresql.conf 中),或者在集群用 initdb 初始化时启用了数据校验和(默认情况)。full_page_writes 也必须被设置为 on,但它在默认情况下是启用的。
如果 pg_rewind 在处理过程中失败,那么目标的数据目录很可能处于无法恢复的状态。在这种情况下,建议进行一次全新的备份。
由于 pg_rewind 会从源完整地复制配置文件,在重启目标服务器之前可能需要修正用于恢复的配置,特别是当目标将被重新作为源的后备引入时。如果在回卷操作完成后重启服务器但没有配置恢复,目标可能再次与主服务器分叉。
如果 pg_rewind 发现它无法直接写入的文件,它会立刻失败。例如,当源服务器和目标服务器对只读 SSL 密钥和证书使用相同的文件映射时,就可能发生这种情况。如果目标服务器上存在这样的文件,建议在运行 pg_rewind 之前移除它们。在执行回卷之后,其中一些文件可能已经从源复制过来,在这种情况下可能需要移除被复制的数据,并恢复回卷之前所使用的链接集合。
pg_rewind 接受下列命令行参数:
-D directory--target-pgdata=directory此选项指定要与源服务器同步的目标数据目录。在运行 pg_rewind 之前,目标服务器必须已被干净地关闭。
--source-pgdata=directory指定源服务器数据目录的文件系统路径,目标数据目录将与该源服务器同步。此选项要求源服务器已被干净地关闭。
--source-server=connstr指定一个 libpq 连接字符串,用于连接到要用来同步目标的源 PostgreSQL 服务器。该连接必须是一个普通(非复制)连接,其角色要有足够的权限在源服务器上执行 pg_rewind 所使用的函数(详见注记一节),或者是一个超级用户角色。此选项要求源服务器正在运行并且接受连接。
-R--write-recovery-conf 在输出目录中创建 standby.signal 并把连接设置追加到 postgresql.auto.conf 中。只有当在连接字符串或 environment variable 中显式指定了 dbname 时,dbname 才会被记录。使用此选项时必须指定 --source-server。
-n--dry-run执行除实际修改目标目录之外的所有操作。
-N--no-sync 默认情况下,pg_rewind 会等待所有文件被安全地写入磁盘。此选项会让 pg_rewind 不等待就返回,这样更快,但意味着一次随后的操作系统崩溃可能会让数据目录损坏。一般来说,此选项对测试有用,但不应在生产安装中使用。
-P--progress启用进度报告。开启此选项后,在从源集群复制数据期间会给出近似的进度报告。
-c--restore-target-wal 使用目标集群配置中定义的 restore_command,在这些文件已不再位于 pg_wal 目录中时,从 WAL 归档取回 WAL 文件。
--config-file=filename 为目标集群使用指定的主服务器配置文件。当 pg_rewind 在此集群上内部使用 postgres 命令执行回卷操作时(在取回 restore_command 时使用了 -c/--restore-target-wal 选项,以及在强制完成崩溃恢复时),这一点会对它产生影响。
--debug打印详细的调试输出,这些输出主要对调试 pg_rewind 的开发者有用。
--no-ensure-shutdownpg_rewind 要求目标服务器在回卷之前已被干净地关闭。默认情况下,如果目标服务器没有被干净地关闭,pg_rewind 会先以单用户模式启动目标服务器以完成崩溃恢复,然后再停止它。通过传入此选项,pg_rewind 会跳过这一步,并且在服务器未被干净地关闭时立刻报错退出。在这种情况下,用户需要自行处理该状况。
--sync-method=method 当被设置为 fsync(默认值)时,pg_rewind 会递归地打开并同步数据目录中的所有文件。对文件的搜索将跟随 WAL 目录和每个已配置表空间的符号链接。
在 Linux 上,可以改用 syncfs 来要求操作系统同步包含数据目录、WAL 文件和每个表空间的整个文件系统。请参见 recovery_init_sync_method 以了解使用 syncfs 时需要注意的事项。
当使用 --no-sync 时,此选项没有效果。
-V--version显示版本信息,然后退出。
-?--help显示帮助,然后退出。
当使用 --source-server 选项时,pg_rewind 还会使用 libpq 支持的环境变量(参见 Section 32.15)。
环境变量 PG_COLOR 指定是否在诊断消息中使用颜色。可能的值是 always、auto 和 never。
当使用一个联机集群作为源来执行 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;
基本思想是把所有文件系统级别的更改从源集群复制到目标集群:
从源集群的时间线历史从目标集群分叉出去的那个点之前的最后一个检查点开始,扫描目标集群的 WAL 日志。对于每一条 WAL 记录,记录其中被触碰过的每一个数据块。这样就得到了在源集群分叉出去之后,目标集群中所有被更改过的数据块的列表。如果某些 WAL 文件已经不再可用,请尝试重新运行 pg_rewind 并带上 -c 选项,以便在 WAL 归档中搜索缺失的文件。
使用直接文件系统访问(--source-pgdata)或 SQL(--source-server),把所有那些已更改的块从源集群复制到目标集群。此时关系文件所处的状态等价于:源和目标的 WAL 时间线分叉点之前最后一次完成的检查点那一时刻的状态,再加上分叉之后目标上被更改过的那些块在源上的当前状态。
把所有其他文件(包括新的关系文件、WAL 段、pg_xact 和配置文件)从源集群复制到目标集群。与基础备份类似,从源集群复制的数据中会省略目录 pg_dynshmem/、pg_notify/、pg_replslot/、pg_serial/、pg_snapshots/、pg_stat_tmp/ 和 pg_subtrans/ 的内容。文件 backup_label、tablespace_map、pg_internal.init、postmaster.opts、postmaster.pid 和 .DS_Store,以及任何以 pgsql_tmp 开头的文件或目录,都会被省略。
创建一个 backup_label 文件,以便从故障转移时创建的检查点开始 WAL 重放;并配置 pg_control 文件的最小一致性 LSN,该 LSN 在从联机源回卷时被定义为 pg_current_wal_insert_lsn() 的结果,在从已停止的源回卷时则为最后一个检查点的 LSN。
在启动目标时,PostgreSQL 会重放所有必需的 WAL,最终得到一个处于一致状态的数据目录。