pg_rewind

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目录,或使用-c选项运行pg_rewind以自动从WAL存档检索它们。pg_rewind的使用并不限于失效的场景,例如一个后备服务器可能被提升、运行一些写事务,然后被倒回再次成为一个后备。

在运行pg_rewind之后,需要完成WAL重放以使数据目录处于一致状态。当目标服务器再次启动时,它将进入归档恢复,并从分歧点之前的最后一个检查点重放源服务器中生成的所有 WAL。当pg_rewind被运行时有某些 WAL 在源服务器上不可用,并且因此无法被pg_rewind会话所复制,则在目标服务器被启动时必须让这些 WAL 可用。 这可以通过在目标数据目录中创建一个recovery.signal文件并且在postgresql.conf中配置适合的restore_command来实现。

pg_rewind要求目标服务器在postgresql.conf中启用了wal_log_hints选项,或者在用initdb初始化集簇时启用了数据校验。目前默认情况下这两者都没有被打开。full_page_writes也必须被设置为on,这是默认的。

警告

如果在处理时pg_rewind失败,则目标的数据目录很可能不在可恢复的状态。在这种情况下,推荐创建一个新的备份。

由于 pg_rewind 完全从源复制配置文件,因此可能需要在重新启动目标服务器之前更正用于恢复的配置,特别是当目标服务器作为源的备用服务器重新引入时。 如果在倒带操作完成后重新启动服务器但未配置恢复,则目标可能会再次与主服务器分离。

如果pg_rewind发现它无法直接写入的文件,它将立刻失败。例如当源服务器和目标服务器为只读的SSL密钥及证书使用相同的文件映射,就会发生这种情况。如果在目标服务器上存在这样的文件,推荐在运行pg_rewind之前移除它们。在做了rewind之后,一些那样的文件可能已经被从源服务器拷贝,这样就有必要移除已经拷贝的数据并且恢复到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中。--source-server对于此选项是必需的。

-n
--dry-run

做除了实际修改目标目录之外的其他所有事情。

-N
--no-sync

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

-P
--progress

启用进度报告。在从源集簇拷贝数据时,打开这个选项将会发送一个近似的进度报告。

-c
--restore-target-wal

如果在pg_wal目录中不再可用这些文件,请使用在目标群集配置中定义的restore_command从WAL存档中检索WAL文件。

--debug

打印冗长的调试输出,这主要对于调试pg_rewind的开发者有用。

--no-ensure-shutdown

pg_rewind 要求目标服务器在倒带之前彻底关闭。 默认情况下,如果目标服务器没有完全关闭,pg_rewind 会以单用户模式启动目标服务器,先完成崩溃恢复,然后将其停止。 通过传递这个选项,如果服务器没有完全关闭,pg_rewind 会跳过这个并立即出错。 在这种情况下,用户应该自己处理这种情况。

-V
--version

显示版本信息然后退出。

-?
--help

显示帮助然后退出。

环境

在使用--source-server选项时,pg_rewind也使用libpq支持的环境变量(见第 34.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;

当使用近期升级的在线群集作为源执行pg_rewind时,必须在升级后执行CHECKPOINT以便其控制文件反映最新的时间线信息, pg_rewind使用这些信息检查目标群集是否可以使用指定的源群集倒回。

如何工作

其基本思想是从源集簇拷贝所有文件系统级别的改变到目标集簇:

  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.opts以及postmaster.pid,以及任何以pgsql_tmp开始的文件或目录都会被忽略。

  4. 创建一个backup_label文件,在故障转移时创建的检查点处开始WAL重放,并将pg_control文件配置为最小一致性LSN,该LSN定义为从活动源回放时的pg_current_wal_insert_lsn()结果,或从停止的源回放时的最后一个检查点LSN。

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