当前位置: 首页 > 工具软件 > pg_rewind > 使用案例 >

pg_rewind到底能做什么?

罗业
2023-12-01

我们知道postgresql的主从切换有点麻烦,或者说操作步骤要求很严格。可能我们经常遇到这种情况,在没有将主库杀死的情况下将备库提升为主,这时主备库可能由于某种原因都在提供写入操作,这时发生脑裂,如果不考虑数据丢失因素,这时我们可能想将原来的主库以备库的模式重新加入集群,但是主备库此时的时间线已经偏离了,这时就需要我们的pg_rewind工具了。

pg_rewind相比pg_basebackup和rsync这样的工具来说,优势是它不需要从源目录拷贝所有的数据文件,而是会对比时间线发生偏离的点,只拷贝变化过的文件,这样对于数据量很大的情况下速度更快。

备库上运行pg_rewind会使得数据库进入恢复状态,备库会从主库读取必要的wal文件,如果源库上因为跑了很长一段时间造成wal丢失,则可以手工从归档目录进行拷贝。

下面的实验简单演示一下pg_rewind的使用:

环境:192.168.1.1(主),192.168.1.2(从)
前提:配置好主从同步,开启wal_log_hints和full_page_writes参数,流复制的配置以及原理等相关详细知识请参考我之前的文章,这里不再赘述。

主库查看同步状态:

postgres=# select * from pg_stat_replication;
-[ RECORD 1 ]----+------------------------------
pid              | 10984
usesysid         | 16384
usename          | replica
application_name | s1
client_addr      | 192.168.1.2
client_hostname  | 
client_port      | 40578
backend_start    | 2019-09-11 13:57:53.525226+08
backend_xmin     | 
state            | streaming
sent_lsn         | 0/4002180
write_lsn        | 0/4002180
flush_lsn        | 0/4002180
replay_lsn       | 0/4002180
write_lag        | 
flush_lag        | 
replay_lag       | 
sync_priority    | 1
sync_state       | sync

备库执行升主操作:

[postgres@DB2 ~]$ pg_ctl promote -D /pgdata
waiting for server to promote.... done
server promoted

查看状态发现主备此时都是生产状态,两个库都可以接受写入,其实就是脑裂的状态:

[postgres@DB1 ~]$ pg_controldata -D /pgdata |grep cluster
Database cluster state:               in production
[postgres@DB2 ~]$ pg_controldata /pgdata/ |grep cluster
Database cluster state:               in production

修改老主库的synchronous_standby_name参数,这里修改的意义是如果不进行修改那么主库写的东西还会向原来的备库同步,而此时已经无法同步,就会hang在那,所以我们要取消原来的同步关系。

postgres=# alter system set synchronous_standby_names='';
ALTER SYSTEM
postgres=# \q
[postgres@DB1 pg_wal]$ pg_ctl reload -D /pgdata/
server signaled

这时在新主库执行写入操作:

postgres=# insert into t values(2);
INSERT 0 1
postgres=# select * from t;
 id 
——
  2
(1 row)

原主库也执行写入操作,模拟时间线偏离:

postgres=# insert into t values(1);
INSERT 0 1
postgres=# select * from t;
 id 
——
  1
(1 row)

接下来开始使用pg_rewind进行老主库重搭,变为备库角色。

停止老主库,一定要干净的关闭:

[postgres@DB1 ~]$ pg_ctl stop -D /pgdata/
waiting for server to shut down..... done
server stopped

执行pg_rewind,注意新主库里面要配置pg_hba.conf选项。

[postgres@DB1 pg_wal]$ pg_rewind -D '/pgdata' --source-server='host=192.168.1.2 user=postgres dbname=postgres connect_timeout=2' -P --dry-run
connected to server
servers diverged at WAL location 0/10017448 on timeline 1
could not open file "/pgdata/pg_wal/000000010000000000000010": 没有那个文件或目录

could not find previous WAL record at 0/10017448
Failure, exiting

发现报错,提示xlog目录下没有000000010000000000000010这个日志文件,因为我们设置了归档,而且wal_keep_segments没有设置,所以在数据库关闭时,wal日志归档到了归档目录,此时我们将归档目录的该日志拷贝过来,再次执行:

[postgres@DB1 pg_wal]$ cp /pgarch/000000010000000000000010 /pgdata/pg_wal/
[postgres@DB1 pg_wal]$ pg_rewind -D '/pgdata' --source-server='host=192.168.1.2 user=postgres dbname=postgres connect_timeout=2' -P --dry-run
[postgres@DB1 pg_wal]$ pg_rewind -D '/pgdata' --source-server='host=192.168.1.2 user=postgres dbname=postgres connect_timeout=2' -P 
connected to server
servers diverged at WAL location 0/10017448 on timeline 1
rewinding from last common checkpoint at 0/F000098 on timeline 1
reading source file list
reading target file list
reading WAL in target
need to copy 52 MB (total source directory size is 70 MB)
53302/53302 kB (100%) copied
creating backup label and updating control file
syncing target data directory
Done!

原主库配置recovery.conf

vi recovery.conf
standby_mode = 'on'
primary_conninfo = 'host=192.168.1.2 port=5432 user=replica password=replica application_name=old_master'
recovery_target_timeline = 'latest'

启动原主库,并查看数据,发现原主库插入的1已经没有,在新主库上插入的2已经同步过来,新的主备关系也正常了。

[postgres@DB1 pgdata]$ pg_ctl start -D /pgdata/ -l logfile
waiting for server to start.... done
server started
postgres=# select * from t;
 id 
——
  2
(1 row)
 类似资料: