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之前将其移除。回卷完成后,其中一些文件可能已经从源复制过来,这种情况下可能需要删除复制过来的数据,并恢复回卷前使用的那组链接。
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中。只有当连接字符串或环境变量中显式指定了 dbname 时,才会记录 dbname。使用此选项时,必须指定--source-server。
-n--dry-run #执行除实际修改目标目录之外的所有操作。
-N--no-sync #默认情况下,pg_rewind会等待所有文件都安全写入磁盘。此选项会使pg_rewind不等待就返回,这样虽然更快,但也意味着如果随后发生操作系统崩溃,数据目录可能会损坏。通常,这个选项适合测试,但不应在生产环境中使用。
-P--progress #启用进度报告。打开该选项后,在从源集簇复制数据时会给出大致的进度信息。
-c--restore-target-wal #如果这些文件在pg_wal目录中已不可用,则使用目标集簇配置中定义的restore_command从 WAL 归档中取回 WAL 文件。
--config-file=filename #为目标集簇使用指定的主配置文件。当pg_rewind在该集簇上内部使用postgres命令执行回卷操作时,这一选项会对其产生影响(包括使用-c/--restore-target-wal获取restore_command以及强制完成崩溃恢复时)。
--debug #打印详细的调试输出,这些输出主要对调试pg_rewind的开发人员有用。
--no-ensure-shutdown #pg_rewind要求在回卷前目标服务器已正常关闭。默认情况下,如果目标服务器未正常关闭,pg_rewind会先以单用户模式启动目标服务器以完成崩溃恢复,然后再将其停止。指定此选项后,pg_rewind会跳过这一步;如果服务器未正常关闭,它会立即报错。在这种情况下,用户应自行处理。
--sync-method=method #设为fsync(默认值)时,pg_rewind会递归打开并同步数据目录中的所有文件。搜索文件时会跟随 WAL 目录及每个已配置表空间的符号链接。
在 Linux 上,也可以改用syncfs,请求操作系统同步包含数据目录、WAL 文件以及各个表空间的整个文件系统。关于使用syncfs时需要注意的限制,请参见recovery_init_sync_method。
使用--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 文件已经不可用,请尝试使用-c选项重新运行pg_rewind,以便在 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 设定为:如果从运行中的源执行回卷,则使用pg_current_wal_insert_lsn()的结果;如果从已停止的源执行回卷,则使用最后一个检查点的 LSN。
启动目标时,PostgreSQL会重放所有必需的 WAL,从而使数据目录达到一致状态。
如果您发现文档中有不正确的内容、与您使用特定功能的经验不符或需要进一步说明,请使用此表单来报告文档问题。