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
目录,或者通过配置recovery.conf
在启动时取得。pg_rewind的使用并不限于故障切换的场景,例如一个后备服务器可能被提升、运行一些写事务,然后被倒回再次成为一个后备。
当目标服务器在运行了pg_rewind之后第一次启动时,它将进入到恢复模式并且重放源服务器在分叉点之后产生的所有 WAL。如果运行pg_rewind时有些 WAL 在源服务器上找不到,并且因此无法被pg_rewind复制过来,则在目标服务器被启动时必须让这些 WAL 可用。这可以通过在目标数据目录中创建一个recovery.conf
文件并且在其中使用一个适当的restore_command
来实现。
pg_rewind要求目标服务器在postgresql.conf
中启用了wal_log_hints选项,或者在用initdb初始化集簇时启用了数据校验。目前默认情况下这两者都没有被打开。full_page_writes也必须被设置为on
,这是默认的。
pg_rewind接受下列命令行参数:
-D directory
--target-pgdata=directory
这个选项指定要与源数据目录同步的目标数据目录。在运行pg_rewind之前目标服务器必须被干净地关闭。
--source-pgdata=directory
指定要和目标服务器同步的源服务器的数据目录的文件系统路径。这个选项要求源服务器必须被干净地关闭。
--source-server=connstr
指定一个 libpq 连接串用于连接要与目标服务器同步的源PostgreSQL服务器。该连接必须是一个具有超级用户访问权限的普通(非复制)连接。这个选项要求源服务器正在运行且不处于恢复模式。
-n
--dry-run
做除了实际修改目标目录之外的其他所有事情。
-P
--progress
启用进度报告。在从源集簇拷贝数据时,打开这个选项将会发送一个近似的进度报告。
--debug
打印冗长的调试输出,这主要对于调试pg_rewind的开发者有用。
-V
--version
显示版本信息然后退出。
-?
--help
显示帮助然后退出。
在使用--source-server
选项时,pg_rewind也使用libpq支持的环境变量(见第 33.14 节)。
其基本思想是从源集簇拷贝所有文件系统级别的改变到目标集簇:
以源集簇的时间线历史从目标集簇分叉出来的点之前的最后一个检查点为起点,扫描目标集簇的 WAL 日志。对于每一个 WAL 记录,读取每一个被动过的数据块。这会得到在目标集簇中从源集簇被分支出去以后所有被更改过的数据块列表。
使用直接的文件系统访问(--source-pgdata
)或者 SQL (--source-server
),把所有那些更改过的块从源集簇拷贝到目标集簇。
把所有其他诸如pg_xact
和配置文件(除了关系文件之外所有的东西)从源集簇拷贝到目标集簇。
从源集簇应用 WAL,从失效处创建的检查点开始(严格来说,pg_rewind并不应用 WAL,它只是创建一个备份标签文件,该文件让PostgreSQL从那个检查点开始向前重放所有 WAL)。