PostgreSQL 12 的流复制与之前的版本有所不同,主要有以下几点区别:
PG12 将原有的属于 recovery.conf
配置文件中配置项迁移到了 postgresql.conf
文件中,在新系统中如果存在 recovery.conf
文件,数据库将无法启动;
文件 recovery.signal
和 standby.signal
用于切换数据库为非主(non-primary)模式;
trigger_file
被修改为 promote_trigger_file
,并且只能在 postgresql.conf
可在配置文件或服务器命令行进行配置;
最后,standby_mode
参数被移除了。
详细说明请移步官网 。本文将在 Ubuntu 18.04 LTS 下搭建 PG12 的流复制系统。
安装数据库 我们在主节点下载 PostgreSQL 12.2 源码,并采用如下命名进行编译安装:
1 2 $ ./configure --prefix=$HOME /pg12.2 $ make -j 4 && make install
随后将其拷贝到从节点。为了方便我们可以先配置环境变量,如下所示:
1 2 3 4 5 6 7 8 9 $ cd $HOME /pg12.2$ cat <<END > pg12.2-env.sh export PGHOME=$PWD export PGDATA=\$PGHOME/pgdata export PATH=\$PGHOME/bin:\$PATH export LD_LIBRARY_PATH=\$PGHOME/lib:\$LD_LIBRARY_PATH END $ source pg12.2-env.sh
我们接下来将在主节点 192.168.56.3 和从节点 192.168.56.101 上搭建 PostgreSQL 流复制。
初始化数据库 在主节点上初始化并启动数据库。
1 2 $ initdb $ pg_ctl -l log start
配置数据库 接着,我们需要修改监听地址,当修改之后需要重启。
1 2 $ psql -c "ALTER SYSTEM SET listen_addresses TO '*'" postgres $ pg_ctl -l log restart
我们可以不必在主节点上设置任何其他参数来进行简单的复制设置,因为默认设置已经适用。
现在,我们需要一个用户用于流复制。
1 $ psql -c "CREATE USER replicator WITH REPLICATION ENCRYPTED PASSWORD 'P@ssw0rd'" postgres
最后,我们需要配置连接以便从节点可以连接主节点进行复制,我需要修改 pg_hba.conf
配置文件。如果我们允许故障切换,那么可能还需要主节点可以连接从节点。
1 2 $ echo "host replication replicator 192.168.56.0/24 md5" >> $PGDATA /pg_hba.conf$ psql -c "SELECT pg_reload_conf()" postgres
备份数据库 现在,我们可以在从节点使用 pg_basebackup
来做一个主库的基础备份。当我们创建备份时可以指定 -R
选项在数据目录中生成特定于复制的文件和配置。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 $ source $HOME /pg12.2/pg12.2-env.sh$ pg_basebackup -h 192.168.56.3 -U replicator -D $PGDATA -R -Fp -Xs -P Password: 23652/23652 kB (100%), 1/1 tablespace $ ls $PGDATA PG_VERSION pg_commit_ts pg_logical pg_serial pg_subtrans pg_xact backup_label pg_dynshmem pg_multixact pg_snapshots pg_tblspc postgresql.auto.conf base pg_hba.conf pg_notify pg_stat pg_twophase postgresql.conf global pg_ident.conf pg_replslot pg_stat_tmp pg_wal standby.signal $ cat $PGDATA /postgresql.auto.conf# Do not edit this file manually! # It will be overwritten by the ALTER SYSTEM command . listen_addresses = '*' primary_conninfo = 'user=replicator password=''P@ssw0rd'' host=192.168.56.3 port=5432 sslmode=disable sslcompression=0 gssencmode=disable krbsrvname=postgres target_session_attrs=any'
从下面我们可以看到,备库有一个名为 standby.signal
的文件,该文件没有任何内容,它仅仅是用于 PostgreSQL 确定其状态。如果该文件不存在,我们应该在备库上创建该文件。
此外,我们还需要注意到 postgresql.auto.conf
文件中的 primary_conninfo
参数,该参数在 PG12 之前是存放在 recovery.conf
文件中,并且还有一个参数 standby_mode = on
。
启动备库 现在我们使用下面的命令启动备库:
我们可以在主库上查看流复制相关信息:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 postgres=# \x Expanded display is on. postgres=# select * from pg_stat_replication ; -[ RECORD 1 ]----+------------------------------ pid | 31970 usesysid | 16385 usename | replicator application_name | walreceiver client_addr | 192.168.56.101 client_hostname | client_port | 60384 backend_start | 2020-02-19 23:07:21.410168+08 backend_xmin | state | streaming sent_lsn | 0/3000148 write_lsn | 0/3000148 flush_lsn | 0/3000148 replay_lsn | 0/3000148 write_lag | flush_lag | replay_lag | sync_priority | 0 sync_state | async reply_time | 2020-02-19 23:07:31.644624+08
我们可以看到,默认情况下 PG 采用异步复制。
同步复制 我们接下来可以修改 synchronous_standby_names
从而使从节点由异步节点改变为同步节点。首先我们在主节点上做如下改变:
1 2 $ psql -c "ALTER SYSTEM SET synchronous_standby_names TO 'standby'" postgres $ psql -c "SELECT pg_reload_conf()" postgres
接着,在从节点修改 primary_conninfo
参数,并在其中加入 application_name=standby
,并重启,如下所示:
1 2 3 4 5 6 7 $ cat $PGDATA/postgresql.auto.conf # Do not edit this file manually! # It will be overwritten by the ALTER SYSTEM command. listen_addresses = '*' primary_conninfo = 'user=replicator password=''P@ssw0rd'' host=192.168.56.3 port=5432 sslmode=disable sslcompression=0 gssencmode=disable krbsrvname=postgres target_session_attrs=any application_name=standby' $ pg_ctl -l log restart
接下来我们可以在主节点进行验证:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 postgres=# select * from pg_stat_replication ; -[ RECORD 1 ]----+------------------------------ pid | 32052 usesysid | 16385 usename | replicator application_name | standby client_addr | 192.168.56.101 client_hostname | client_port | 60386 backend_start | 2020-02-19 23:18:30.358057+08 backend_xmin | state | streaming sent_lsn | 0/3025410 write_lsn | 0/3025410 flush_lsn | 0/3025410 replay_lsn | 0/3025410 write_lag | 00:00:00.001529 flush_lag | 00:00:00.001529 replay_lag | 00:00:00.001529 sync_priority | 1 sync_state | sync reply_time | 2020-02-19 23:18:30.480227+08
提升从节点 当主节点掉线时,我们可能希望将从节点提升为主节点,此时,我们需要使用到 promote_trigger_file
参数。
首先,我们在主节点和从节点看看它们各自的状态。
1 2 3 4 5 $ postgres=# select pg_is_in_recovery(); -- 主节点 pg_is_in_recovery ------------------- f (1 row)
1 2 3 4 5 postgres=# select pg_is_in_recovery(); -- 从节点 pg_is_in_recovery ------------------- t (1 row)
接着,我们在从节点的 postgresql.conf
文件中加入 promote_trigger_file=/tmp/.tfile
配置,这是,当主节点掉线时,我们在从节点创建 /tmp/.tfile
文件,那么从节点将自动提升为主。
如果我们在主节点没有掉线的情况下,创建了 /tmp/.tfile
这个触发文件,那么此时从节点将创建一个新的时间线,从而导致主从不一致。
参考 [1] https://www.postgresql.org/docs/12/release-12.html [2] https://www.postgresql.org/docs/12/runtime-config-replication.html#GUC-PROMOTE-TRIGGER-FILE [3] https://www.percona.com/blog/2019/10/11/how-to-set-up-streaming-replication-in-postgresql-12/