PostgreSQL 教程: 使用 pg_rewind 重新同步已降级的主机

七月 30, 2024

摘要:在本教程中,我们将讨论,对于从复制集群中分离出来的原主服务器,如何将其作为备用服务器重新添加到集群中,而无需从头开始重建它。

目录

准备工作

这适用于已执行过故障转移的复制集群。此外,它仅在参数wal_log_hintsdata_checksums启用时才起作用。但是,设置这两个参数可能会带来一些性能损失,但wal_log_hints产生的开销较少。

wal_log_hints:当此参数处于启用状态时,PostgreSQL 服务器会在检查点后第一次修改每个磁盘页面时,将该页面的全部内容写入WAL,即使对于所谓的提示位的非关键修改也会如此。更改此参数需要重启 PostgreSQL 集群。必须在复制集群中的所有 PostgreSQL 服务器上,执行以下操作:

$ psql -c "ALTER SYSTEM SET wal_log_hints TO 'ON'"
$ pg_ctl -D $PGDATA restart

此外,自故障转移以来的所有 WAL 段都必须存在,才能完成回转。

操作步骤

我们将使用以下步骤来执行此操作:

1. 如果需要,可以在旧主机上手动关闭 PostgreSQL:

$ pg_ctl -D $PGDATA stop

2. 运行 pg_rewind:

$ pg_rewind -D /var/lib/pgsql/12/data --sourceserver="host=<new_master_IP> port=5432 user=postgres dbname=postgres password=secret"
The servers diverged at WAL POSITION 0/9BC9E268 ON timeline 1.
could NOT OPEN file "/var/lib/pgsql/12/data/pg_wal/00000001000000000000009B": No such file OR directory

could NOT find previous WAL record at 0/9BC9E268
Failure, exiting

3. 此处,主机上只保留了很少的 WAL 段,所以现在需要复制一些回来:

$ ls -l /var/lib/pgsql/12/data/pg_wal/
-rw------- 1 postgres postgres 16777216 Apr  4 13:51 0000000100000000000000B5
-rw------- 1 postgres postgres 16777216 Apr  4 13:51 0000000100000000000000B6
-rw------- 1 postgres postgres       42 Apr  4 13:49 00000002.history
drwx------ 2 postgres postgres     4096 Apr  4 13:51 archive_status/

所以,我们只需要复制从 9B 到 B5 的所有 WAL 段:

$ cp /backup/archive/00000001000000000000009[BCDEF] /var/lib/pgsql/12/data/pg_wal/
$ cp /backup/archive/0000000100000000000000A? /var/lib/pgsql/12/data/pg_wal/
$ cp /backup/archive/0000000100000000000000B[01234] /var/lib/pgsql/12/data/pg_wal/

4. 再次运行 pg_rewind:

$ pg_rewind -D /var/lib/pgsql/12/data --sourceserver="host=<new_master_IP> port=5432 user=postgres dbname=postgres password=secret"
The servers diverged at WAL position 0/9BC9E268 on timeline 1.
Rewinding from last common checkpoint at 0/9B8B20D0 on timeline 1
Done!

5. 添加primary_conninfo设置,创建 standby.signal 文件:

$ echo "primary_conninfo = 'user=replicator password=secret host=<new_master_IP> port=5432 sslmode=prefer sslcompression=0 gssencmode=prefer krbsrvname=postgres target_session_attrs=any'" >> $PGDATA/postgresql.auto.conf
$ echo "standby_mode = 'ON'" >> $PGDATA/postgresql.auto.conf
$ touch $PGDATA/standby.signal

6. 启动备用服务器(M1):

$ pg_ctl -D $PGDATA start

怎么做到的

一旦执行过故障转移,新主服务器的时间线会发生变化,并且会与原主服务器不同。此时,我们可以使用 pg_rewind,从新的主服务器重新同步旧的主服务器。这样,我们可以将旧主服务器作为备用服务器添加到集群中,而无需重建它。为了实现这一点,我们需要确保旧主服务器不接受写入,并在故障转移时关闭。或者,我们可以使用步骤 1 中使用的命令,手动关闭在旧主机(M1)上运行的 Postgres。

一旦旧的主服务器被关闭,我们就可以参照步骤 2 使用 pg_rewind,将旧主服务器倒回到应该从新主服务器开始复制的点。在命令中,唯一需要更改的是主机,该主机必须是新主机的 IP 或主机名。此外,您还应该正确修改用户和密码。

执行 pg_rewind 所需的时间各不相同。它可能更快或更慢,具体取决于故障转移时发生的更改。完成第 2 步后,我们应该将适当的参数和文件放在一个位置,表明旧主服务器是备用服务器。我们可以参考第 3 步,该步骤讲述了如何在旧主机(M1)的 postgresql.auto.conf 文件中,设置primary_conninfostandby_mode这两个参数。添加参数后,我们可以创建一个空文件 standby.signal,如步骤 3 所示。然后,我们可以在服务器 M1 上简单地启动 PostgreSQL 集群。