pg_rewind是一个用于把一个PostgreSQL数据目录与另一个从该目录中复制出来的数据目录同步,在集簇的时间线分叉以后,同步一个PostgreSQL集簇和同一集簇的另一份拷贝的工具。一种典型的场景是在失效后让一个旧的主服务器重新上线,同时有一个后备机跟随着新的主机。也就是说,在主备不同步后,我们也许不必重建备库以修复流复制环境,使用pg_rewind解决时间分叉就可以修复同步失败的问题。
pg_rewind要求目标服务器在postgresql.conf中启用了wal_log_hints选项,或者在用initdb初始化集簇时启用了数据校验。目前默认情况下这两者都没有被打开。full_page_writes也必须被设置为on,这个是默认的。
以下介绍两个pg_rewind实践方案步骤:
第一部分 回退只读从库
1.1激活从库
激活只读从库,使从库能够读写
$ pg_ctl promote -D /pgdata/data
1.2写入从库
在从库中写入数据,生成wal日志
$ pgbench -M prepared -v -r -P 1 -c 4 -j 4 -T 120 -p 5432
starting vacuum...end.
starting vacuum pgbench_accounts...end.
此时从库和主库已不在同一个时间线上
从库时间线
$ pg_controldata | grep TimeLineID
Latest checkpoint's TimeLineID: 9
Latest checkpoint's PrevTimeLineID: 9
主库时间线
$ pg_controldata | grep TimeLineID
Latest checkpoint's TimeLineID: 8
Latest checkpoint's PrevTimeLineID: 8
1.3修复从库
查看切换点
$ ll $PGDATA/pg_wal/*.history
查看最新时间线的.history文件
$ cat 00000009.history
5/5A000060
从00000009000000050000005A开始,所有的wal必须存在从库pg_wal目录中。如果已经覆盖了,必须从归档目录拷贝到从库pg_wal目录中,也可以直接将归档文件全部拷贝到pg_wal目录下
$ cp /mnt/server/archivedir/* /pgdata/data/pg_wal/ #/mnt/server/archivedir/为归档目录
停掉从库
$ pg_ctl stop -m fast -D /pgdata/data
测试修复是否能够成功
$ pg_rewind -n -D /pgdata/data --source-server="hostaddr=192.168.22.128 user=postgres port=5432"
pg_rewind: servers diverged at WAL location 5/5A000060 on timeline 8
pg_rewind: rewinding from last common checkpoint at 5/59000060 on timeline 8
pg_rewind: Done!
可以修复,直接修复
$ pg_rewind -D /pgdata/data --source-server="hostaddr=192.168.22.128 user=postgres port=5432"
pg_rewind: servers diverged at WAL location 5/5A000060 on timeline 8
pg_rewind: rewinding from last common checkpoint at 5/59000060 on timeline 8
pg_rewind: Done!
修改配置文件postgresql.auto.conf
$ vi postgresql.auto.conf
primary_conninfo = 'user=repl passfile=''/home/postgres/.pgpass'' host=192.168.22.128 port=5432 sslmode=prefer sslcompression=0 gssencmode=prefer krbsrvname=postgres target_session_attrs=any'
restore_command = 'cp /mnt/server/archivedir/%f %p'
recovery_target_timeline = 'latest'
删除错误时间线上产生的归档,即走到时间线00000009上的归档
$ mkdir /mnt/server/archivedir/error_tl_9
$ mv 00000009* error_tl_9
创建从库标识文件
$ touch /pgdata/data/standby.signal
1.4启动从库
$ pg_ctl start -D /pgdata/data
在主库上查看流复制同步状态
postgres=# select client_addr,sync_state from pg_stat_replication;
client_addr | sync_state
----------------+------------
192.168.22.128 | async
第二部分 降级读写主库
2.1激活从库
激活只读从库,使从库能够读写
$ pg_ctl promote -D /pgdata/data
2.2写入主、从库
在从库中写入数据,生成wal日志
$ pgbench -M prepared -v -r -P 1 -c 4 -j 4 -T 120 -p 5432
starting vacuum...end.
starting vacuum pgbench_accounts...end.
在主库中写入数据,生成wal日志
$ pgbench -M prepared -v -r -P 1 -c 4 -j 4 -T 120 -p 5432
starting vacuum...end.
starting vacuum pgbench_accounts...end.
此时从库和主库已不在同一个时间线上
从库时间线
$ pg_controldata | grep TimeLineID
Latest checkpoint's TimeLineID: 9
Latest checkpoint's PrevTimeLineID: 9
主库时间线
$ pg_controldata | grep TimeLineID
Latest checkpoint's TimeLineID: 8
Latest checkpoint's PrevTimeLineID: 8
2.3修复老主库
查看切换点
$ ll $PGDATA/pg_wal/*.history
查看最新时间线的.history文件
$ cat 00000008.history
5/37000000
从000000080000000500000037开始,所有的wal必须存在从库pg_wal目录中。如果已经覆盖了,必须从归档目录拷贝到从库pg_wal目录中,也可以直接将归档文件全部拷贝到pg_wal目录下
$ cp /mnt/server/archivedir/* /pgdata/data/pg_wal/ #/mnt/server/archivedir/为归档目录
停掉老主库
$ pg_ctl stop -m fast -D /pgdata/data
测试修复是否能够成功
$ pg_rewind -n -D /pgdata/data --source-server="hostaddr=192.168.22.129 user=postgres port=5432"
pg_rewind: servers diverged at WAL location 5/37000000 on timeline 8
pg_rewind: rewinding from last common checkpoint at 5/37000000 on timeline 8
pg_rewind: Done!
可以修复,直接修复
$ pg_rewind -D /pgdata/data --source-server="hostaddr=192.168.22.129 user=postgres port=5432"
pg_rewind: servers diverged at WAL location 5/37000000 on timeline 8
pg_rewind: rewinding from last common checkpoint at 5/37000000 on timeline 8
pg_rewind: Done!
修改配置文件postgresql.auto.conf
$ vi postgresql.auto.conf
primary_conninfo = 'user=repl passfile=''/home/postgres/.pgpass'' host=192.168.22.128 port=5432 sslmode=prefer sslcompression=0 gssencmode=prefer krbsrvname=postgres target_session_attrs=any'
restore_command = 'cp /mnt/server/archivedir/%f %p'
recovery_target_timeline = 'latest'
老主库创建从库标识文件
$ touch /pgdata/data/standby.signal
2.4启动新从库
$ pg_ctl start -D /pgdata/data
在新主库上查看流复制同步状态
postgres=# select client_addr,sync_state from pg_stat_replication;
client_addr | sync_state
----------------+------------
192.168.22.129 | async
注意事项
当使用在线群集作为源执行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使用这些信息检查目标群集是否可以使用指定的源群集倒回。
原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/237320.html