pg_rewind时间线修复

Posted PostgreSQLChina

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了pg_rewind时间线修复相关的知识,希望对你有一定的参考价值。

作者:杭州美创科技有限公司

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使用这些信息检查目标群集是否可以使用指定的源群集倒回。

以上是关于pg_rewind时间线修复的主要内容,如果未能解决你的问题,请参考以下文章

pg_rewind 源端时间线发生改变 同步失败

postgresql 线同步pg_rewind使用报错及注意

PostgreSQL pg_rewind原理

如何修复重叠的片段

修复线剪切算法的代码

PostgreSQL pg_rewind report error退出分析