Postgresql PG_REWIND 怎么就这样不行
- 2019 年 12 月 17 日
- 筆記
其实PG 早就想到这个问题了,PG有一个独特的命令 pg_rewind 可以帮助你,再造一个你。
我们看看pg_rewind能帮我们什么
pg_rewind 的工作原理有点类似rsync,它可以无缝的读取源目录与目的目录之间不同的数据块,而重复的数据块将不再被读取。这样的方式其实对于上面的问题是一个好的解决方案,因为如果主从复制,任何一方坏了,使用PG_REWIND 可以快速将你认为的数据完全的一方的数据同步到另一方,而不用做全量复制,这样最大的好处就是节省了时间。
当然如果大概率知道checksum的(包括MYSQL的binlog checksum )大多可以想到,怎么知道这两边的数据是否一致,必须的校验块,postgresql 如果要使用pg_rewind 功能需要你做以下的一些设置
1 full_page_writes = on
2 wal_log_hints = on
3 hot_standby = on
4 如果你在初始化数据库集群(postgresql 单机也叫数据库集群,别和真正的集群的含义搞混)做了data checksum 也是可以的。
其主要的工作原理,在目的集群中对比源,与目的端之间的不同点,就是什么时候两个服务器之间的数据开始不同步的。通过知道这些不同点开始进行
1 使用文件系统的方式进行拷贝
2 使用libpq 建立连接的方式将数据进行拷贝
在拷贝数据文件的以外还需要拷贝事务提交的文件,pg_xact 以及配置文件等等。生成backup label 文件,并且指定开始要恢复的 wal 日志点,并应用恢复点以后的日志,并且还要刷新 pg_control 文件(在设置了检查点并刷新日志之后,检查点的位置将保存在文件pg_control中),最后执行initdb -S 将数据刷入到磁盘后,关闭。
问题1 ,PG_REWIND 怎么识别两台PG 是曾经为primary 和 standby的管理
其实就是通过 database system identifier 来鉴别,同样的主从的 database system identifier 的编码是一致的。同时也要看version 与 catalog version number 是否一致。

而关于bakcup label 其中包含了check point ,而后续的复制也是要依靠这个check point 点 目的集群就可以不断应用源集群从CHECKPOINT LOCATION 之后的WAL 日志。
当然其中的原理不光如此,下面就开始做一个实验看看pg_rewind的强大的功能。
首先下面有两台PG , 192.168.198.120 主库 192.168.198.176 从库
通过pg_basebackup 进行数据同步后,在 192.168.198.120 上在进行相关的一些建库,曾表,插入数据的事情,看看PG_REWIND 是否可以进行相关的数据同步
pg_basebackup 命令就不在讲了,默认大家都会了,不会的可以百度,或者看我之前的关于这方面的东西。
1 下面的两个服务器的数据已经是一致的,通过pg_basebackup 进行的复制

2 对176 进行promote 操作,模拟主库失效,从库接替主库,此时主库和从库之间不再有任何关系 (需要修改176 的 postgresql 的监听地址,这点是基础就不再提了)

4 我们在176上进行创建一个pg_rewind库的操作,此时 两个库已经数据不一致了

最后在120 上执行
pg_rewind –target-pgdata=/pgdata/data –source-server='host=192.168.198.176 port=5432 user=repl dbname=postgres password=repl' -P –debug

将数据追齐后,修改120 的配置文件,模拟失效的主库和已经提升为主库的“从库” 数据已经一致了


到这里本来就完事了,但实际上有些评论说pg_rewind 是可以做数据同步的,我是比较感兴趣的,到底 pg_rewind 可不可以做数据同步。
首先我们要确认几点,在达到共识的基础上才能继续下面的工作
1 即使是数据同步,也必须是在之前两个节点之间的关系是主从关系,或者至少是有关系,如果两个节点之间没有任何关系,则这个工作是没有办法做的。
2 数据同步是否需要 promote 操作作为前提,或者直接去修改 recovery.conf 文件
测试1 :
进行数据同步,然后将从库关闭,将recover.conf 变为 recover.done,然后重启动从库,在关闭,变更主库的数据,使用pg_rewind进行数据同步
结果失败,通过失败可以证明,如果主从失败后,想直接通过提升当前从库的方法,在通过 pg_rewind 进行数据同步的想法可以凉快去了

测试2 同步长时间的主库已经和原来的从库(从库已经提升为主库)的数据是否可行,这里的长时间其实也是看数据量,下面的情况就是报找不到pg_wal 文件,这边可以尝试从原来的从库上拷贝缺少的pg_wal 或者开启 archive 等方式保证你的pg_wal 是充足的。

图中源主库报没有00000004000000000000003F 文件,找到原来的从库,现在的主库将这个文件拷贝到原来的主库,则pg_rewind 正常工作。

所以相关的pg_wal 文件也要留存好,最好是有archive 来做数据恢复的后盾。
总结,某些帖子中假想的想通过pg_rewind 来进行数据库之间的复制的想法是不可以的,同时pg_wal 中的日志数据应该进行archive 以防止出现找不到pg_wal 的问题。