POSTGRESQL 主节点失败后, 在多变的情况下重新让他融入复制中

2021-08-19 00:00:00 数据 文件 添加 复制 情况

POSTGRESQL 在主从流复制中,在主库失败切换后,从库变为主库后,如果主库不是因为硬件的原因,想继续拉起来,并且加入到新的复制关系中,一般都会通过pg_rewind的程序来进行拉起来. 但不少问题反馈对pg_rewind在重新拉起旧主库出现问题,到底有什么情况下pg_rewind对你的数据库重新建立复制关系"力不从心", 怎么去避免这样的情况是这篇文字要讨论和提到的.


对于对pg_rewind不熟悉的小伙伴,这里在重新解释,一下PG_REWIND的工作主要是针对源数据目录与目的数据目录的同步,通过拷贝的方式,包含配置文件,PG_REWIND不需要读取所有的未改变的文件,只需要读取变化的文件. 这样将一个失败的主库恢复为从库的速度和效率都是高的. pg_rewind 会评估源和目的集群的时间轴信息,以及偏离点的信息. 另外pg_rewind主要的针对的场景就是主从切换后,主重新加入到新的集群的场景,在wal 日志丢失和不全的情况下,是无法来进行相关的复制的工作的.

另外使用pg_rewind时必须要启用, FPW 和 wal_ log_hint 这两个是必然要开启的选项,否则系统是无法正常使用pg_rewind的.

另外有两点注意,当pg_rewind操作失败后,则目标系统文件损坏,此时只能通过备份的方式来重建"从库",同时对于数据目录中一些"只读文件",使用pg_rewind 时会失败,常见与使用了ssl key 证书的时候.


工作原理:

1  扫描源于目的数据库中后一次相同的checkpoint点之后的信息,并根据开始不同的信息来组织相关的数据块列表,通过wal log中的进行查找

2   针对列表中的数据块通过拷贝的方式,直接在文件系统级别拷贝,其中还包含pg_xact中的文件以及配置文件等等

3   开始应用在切换点后创建的checkpoint点后的wallog数据并进行重放,pg_rewind本身是不会进行相关的工作,而是通过打入一个备份的标签,在节点开启后重放日志,达到终的一致性.



1  正常停止主库


2  提升从库


此时需要注意,如果使用了物理复制槽,则必须确认(新主上也有物理复制槽,否则在此设置连接会失败)

SELECT * FROM pg_create_physical_replication_slot('slot_s1');


以下为手动恢复的过程   

一 情况 (在主库和从库都不修改数据的情况下)

在原主新从执行pg_rewind命令,连接

1   pg_rewind --target-pgdata=/pgdata/data --source-server='host=192.168.198.101 port=5432 user=repl password=repl dbname=postgres' -P


2 在原主新从,添加recovery.conf文件, 具体可以从原从库,上的recovery.done 中拷贝并修改文件,文件的内容



standby_mode = 'on'

primary_conninfo = 'user=repl passfile=''/home/postgres/.pgpass'' host=192.168.198.101 port=5432 sslmode=prefer sslcompression=1 target_session_attrs=any'

primary_slot_name='slot_s1'

recovery_target_timeline='latest'


3  启动主库

4  查询复制建立的情况


二 情况 (主库和从库,新主修改了数据的情况)

1  主库关机

2  提升新从变为新主,并插入数据


3  在新"从"上运行pg_rewind命令

 pg_rewind --target-pgdata=/pgdata/data --source-server='host=192.168.198.101 port=5432 user=repl password=repl dbname=postgres' -P


4  重建recovery.conf

standby_mode = 'on'

primary_conninfo = 'user=repl passfile=''/home/postgres/.pgpass'' host=192.168.198.101 port=5432 sslmode=prefer sslcompression=1 target_session_attrs=any'

primary_slot_name='slot_s1'

recovery_target_timeline='latest'


5  启动新从库并在新的从库上查询新添加的数据




三, (主库和从库,新从库修改了数据的情况)

1   关闭主库

2   将新的从库变为主库

3   启动DOWN及的原主库,并添加数据库,在关闭他

4  pg_rewind --target-pgdata=/pgdata/data --source-server='host=192.168.198.101 port=5432 user=repl password=repl dbname=postgres' -P



5  添加recovery.conf

standby_mode = 'on'

primary_conninfo = 'user=repl passfile=''/home/postgres/.pgpass'' host=192.168.198.101 port=5432 sslmode=prefer sslcompression=1 target_session_attrs=any'

primary_slot_name='slot_s1'

recovery_target_timeline='latest'


6  启动新的从库,查看刚才添加的数据库tt5是否存在, 可以看到原有的tt5已经不存在了.



四, (在主库DOWN机后,DOWN机后的主库和新的主库均变动了数据)


1 关闭主库

2  从库提升为主库

3  在"新主" 上插入数据

4  在"旧主上插入数据"


5  关闭"旧主"

6  执行pg_rewind

pg_rewind --target-pgdata=/pgdata/data --source-server='host=192.168.198.101 port=5432 user=repl password=repl dbname=postgres' -P


7添加recovery.conf

standby_mode = 'on'

primary_conninfo = 'user=repl passfile=''/home/postgres/.pgpass'' host=192.168.198.101 port=5432 sslmode=prefer sslcompression=1 target_session_attrs=any'

primary_slot_name='slot_s1'

recovery_target_timeline='latest'

8  启动新从库(旧主), 查看从库的数据状态



复制状态



以上情况中,pg_rewind都可以将失败的主, 拉起来并和"新主"进行数据同步.


后我们模拟一下,突然掉电的情况,看看是否有其他的变化. 并且在主库上加大压力,通过pg_bench 对数据库进行压力测试

在大量插入数据的过程中直接直接将虚拟机硬关机


此时我们将从库变为主库 

然后启动已经变成孤家寡人的"主库", 然后他将刚才在掉电情况下为写入的数据进行了redo

然后我们重复上面的工作


 pg_rewind --target-pgdata=/pgdata/data --source-server='host=192.168.198.101 port=5432 user=repl password=repl dbname=postgres' -P


配置好复制,启动新的从库



总结: 整体pg_rewind 在多种情况下,都可以保证失败后的数据库重新拉起来并进入新的复制, 但需要注意的两点 

1 如果添加的物理复制槽的,那就需要在新的主库上添加,或确认复制槽的存在

2 加入的从库的数据与主库不一致的会全部被抹去,所以在重新加入的过程中需要注意是否有必要要保留"新从"不一致的数据.



相关文章