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
目录,或者通过配置primary_conninfo 或restore_command在启动时取得。pg_rewind的使用并不限于失效的场景,例如一个后备服务器可能被提升、运行一些写事务,然后被倒回再次成为一个后备。
当目标服务器在运行了pg_rewind之后第一次启动时,它将进入到恢复模式并且重放源服务器在分叉点之后产生的所有 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发现它无法直接写入的文件,它将立刻失败。例如当源服务器和目标服务器为只读的SSL密钥及证书使用相同的文件映射,就会发生这种情况。如果在目标服务器上存在这样的文件,推荐在运行pg_rewind之前移除它们。在做了rewind之后,一些那样的文件可能已经被从源服务器拷贝,这样就有必要移除已经拷贝的数据并且恢复到rewind之前使用的链接集合。
pg_rewind接受下列命令行参数:
-D directory
--target-pgdata=directory
这个选项指定要与源数据目录同步的目标数据目录。在运行pg_rewind之前目标服务器必须被干净地关闭。
--source-pgdata=directory
指定要和目标服务器同步的源服务器的数据目录的文件系统路径。这个选项要求源服务器必须被干净地关闭。
--source-server=connstr
指定一个 libpq 连接串用于连接要与目标服务器同步的源PostgreSQL服务器。 连接必须是常规(非复制)连接,角色具有足够权限执行源服务器上pg_rewind使用的函数(详请参阅备注部分)或超级用户角色。这个选项要求源服务器正在运行且不处于恢复模式。
-n
--dry-run
做除了实际修改目标目录之外的其他所有事情。
-N
--no-sync
默认情况下,pg_rewind
将等待所有文件安全地写入磁盘。
此选项会导致pg_rewind
不等待即可返回,这更快,但意味着后续操作系统崩溃会使同步数据目录损坏。通常情况,此选项可用于测试,但在创建生产安装时不应使用。
-P
--progress
启用进度报告。在从源集簇拷贝数据时,打开这个选项将会发送一个近似的进度报告。
--debug
打印冗长的调试输出,这主要对于调试pg_rewind的开发者有用。
-V
--version
显示版本信息然后退出。
-?
--help
显示帮助然后退出。
在使用--source-server
选项时,pg_rewind也使用libpq支持的环境变量(见第 33.14 节)。
环境变量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;
当使用近期升级的在线群集作为源执行pg_rewind时,必须在升级后执行CHECKPOINT
以便其控制文件反映最新的时间线信息,
pg_rewind使用这些信息检查目标群集是否可以使用指定的源群集倒回。
其基本思想是从源集簇拷贝所有文件系统级别的改变到目标集簇:
以源集簇的时间线历史从目标集簇分叉出来的点之前的最后一个检查点为起点,扫描目标集簇的 WAL 日志。对于每一个 WAL 记录,读取每一个被动过的数据块。这会得到在目标集簇中从源集簇被分支出去以后所有被更改过的数据块列表。
使用直接的文件系统访问(--source-pgdata
)或者 SQL (--source-server
),把所有那些更改过的块从源集簇拷贝到目标集簇。
把所有其他诸如pg_xact
和配置文件(除了关系文件之外所有的东西)从源集簇拷贝到目标集簇。与基础备份类似,在从源集簇拷贝的数据中,目录pg_dynshmem/
、pg_notify/
、pg_replslot/
、pg_serial/
、pg_snapshots/
、pg_stat_tmp/
以及pg_subtrans/
的内容会被忽略。任何以pgsql_tmp
开始的文件或目录都会被忽略,backup_label
、tablespace_map
、pg_internal.init
、postmaster.opts
以及postmaster.pid
也是这样。
从源集簇应用 WAL,从失效处创建的检查点开始(严格来说,pg_rewind并不应用 WAL,它只是创建一个备份标签文件,该文件让PostgreSQL从那个检查点开始向前重放所有 WAL)。