暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

pg_rewind到底能做什么?

数据库架构 2019-09-16
496

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

 

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

 

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

 

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

 

环境:192.168.1.1(主),192.168.1.2(从)

前提:配置好主从同步,开启wal_log_hintsfull_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)


                        好吧,加油吧,扫码关注公众号,更多干货等着你。



                        文章转载自数据库架构,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                        评论