主备环境说明

主机名

IP

角色

端口

master

192.168.20.133

Master

5432

slave

192.168.20.134

Slave

5432

创建流复制

首先在主备服务器上安装好PG数据库,具体安装方法这里不再介绍。

配置hosts

在主、备服务器上都设置

[root@master ~]# cat /etc/hosts
127.0.0.1 localhost
192.168.20.133 master
192.168.20.134 slave

[可选]初始化master数据库

如果新搭建的主备环境,那么需要初始化主库。如果是已经运行的PG,那么就不需要这一步操作。

#切换到postgres账户
[root@master ~]# su - postgres
#初始化data
[postgres@master ~]$ initdb -D $PGDATA
# 启动master数据库
[postgres@master ~]$ pg_ctl start -D $PGDATA

主库创建用户

创建用户用于复制WAL日志。

postgres=# CREATE USER repuser replication LOGIN CONNECTION LIMIT 3 ENCRYPTED PASSWORD '123456';
CREATE ROLE

配置pg_hba.conf

在主库的pg_hba.conf最后一行增加如下:

host replication      repuser         slave          md5

配置postgresql.conf

在主库上配置如下:

listen_addresses = '*' 
port = 5432
max_wal_senders = 10
wal_level = replica
archive_mode = on
archive_command = 'cd ./'
hot_standby = on
wal_keep_segments = 64
full_page_writes = on
wal_log_hints = on

其他可配置参数:
以下四个参数值,在备库上参数值不应小于主库上的值,否则会导致无法启动。

max_connections
max_prepared_transactions
max_locks_per_transaction
max_worker_processes

如果修改参数值大小:

  • 将参数值修改更大
    先修改所有备库,再修改主库
  • 将参数值改小
    先修改主库,再修改备库

重启数据库

systemctl restart postgresql-11

pg_basebackup 创建备库

在slave端的postgres用户下执行:

[postgres@slave ~]$ pg_basebackup -h master -U repuser -D /var/lib/pgsql/11/data/ -X stream -P
Password:
pg_basebackup: initiating base backup, waiting for checkpoint to complete
pg_basebackup: checkpoint completed
pg_basebackup: write-ahead log start point: 0/11000028 on timeline 3
pg_basebackup: starting background WAL receiver
pg_basebackup: created temporary replication slot "pg_basebackup_1734"
31203/31203 kB (100%), 1/1 tablespace
pg_basebackup: write-ahead log end point: 0/110000F8
pg_basebackup: waiting for background process to finish streaming ...
pg_basebackup: base backup completed

修改slave中data目录下的pg_hba.conf最后一行修改如下:

host replication      repuser         master         md5

配置recovery.conf

主库:

[postgres@slave ~]$ cp /usr/pgsql-11/share/recovery.conf.sample /var/lib/pgsql/11/data/recovery.done
[postgres@slave ~]$ vi /var/lib/pgsql/11/data/recovery.done
#编辑内容如下
recovery_target_timeline = 'latest'
standby_mode = on
primary_conninfo = 'host=slave port=5432 user=repuser password=123456'

备库:

[postgres@slave ~]$ cp /usr/pgsql-11/share/recovery.conf.sample /var/lib/pgsql/11/data/recovery.conf
[postgres@slave ~]$ vi /var/lib/pgsql/11/data/recovery.conf
#编辑内容如下
recovery_target_timeline = 'latest'
standby_mode = on
primary_conninfo = 'host=master port=5432 user=repuser password=123456'

验证

查看进程、状态

主库
查看主库的WAL日志发送进程是否正常

[root@master data]# ps -ef|grep walsender
postgres 3274 3229 0 02:40 ? 00:00:00 postgres: walsender repuser 192.168.20.134(49896) streaming 0/180003C8
root 3293 1392 0 02:44 pts/0 00:00:00 grep --color=auto walsender

从库
查看从库WAL日志接收进程是否正常

[root@slave 11]# ps -ef|grep walreceiver
postgres 5942 5935 0 02:40 ? 00:00:00 postgres: walreceiver streaming 0/180003C8
root 6192 3073 0 02:45 pts/0 00:00:00 grep --color=auto walreceiver

主库查看复制状态
流异步复制

lei=# \x on;
Expanded display is on.
lei=# select * from pg_stat_replication;
-[ RECORD 1 ]----+------------------------------
pid | 3274
usesysid | 16774
usename | repuser --复制用户
application_name | walreceiver
client_addr | 192.168.20.134 --从库IP
client_hostname | slave
client_port | 49896
backend_start | 2019-05-30 02:40:58.253032-04
backend_xmin |
state | streaming --流复制
sent_lsn | 0/180003C8
write_lsn | 0/180003C8
flush_lsn | 0/180003C8
replay_lsn | 0/180003C8
write_lag |
flush_lag |
replay_lag |
sync_priority | 0
sync_state | async --异步

测试数据

重启主、备数据库使配置生效

主库

[postgres@master ~]$ psql
psql (11.3)
Type "help" for help.

postgres=# \c lei;
You are now connected to database "lei" as user "postgres".
lei=# select * from test;
id
----
1
1
2
(3 rows)

备库

[postgres@slave ~]$ psql
psql (11.3)
Type "help" for help.

postgres=# \c lei;
You are now connected to database "lei" as user "postgres".
lei=# select * from test;
id
----
1
1
2
(3 rows)

主库插入数据

lei=# insert into test values(3);
INSERT 0 1

从库查询

lei=# select * from test;
id
----
1
1
2
3
(4 rows)

至此,PostgreSQL主从流复制安装部署完成。

附录

区分数据库是主库还是备库方法:

方法1. pg_controldata

主库

[postgres@localhost ~]$ pg_controldata
pg_control version number: 960
Catalog version number: 201608131
Database system identifier: 6362107256088627972
Database cluster state: in production

备库

pg_control version number:            960
Catalog version number: 201608131
Database system identifier: 6362107256088627972
Database cluster state: in archive recovery

方法2.字典表pg_stat_replication

只有主库才能查到数据

lei=# \x on;
Expanded display is on.
lei=# select * from pg_stat_replication;
-[ RECORD 1 ]----+------------------------------
pid | 3274
usesysid | 16774
usename | repuser --复制用户
application_name | walreceiver
client_addr | 192.168.20.134 --从库IP
client_hostname | slave
client_port | 49896
backend_start | 2019-05-30 02:40:58.253032-04
backend_xmin |
state | streaming --流复制
sent_lsn | 0/180003C8
write_lsn | 0/180003C8
flush_lsn | 0/180003C8
replay_lsn | 0/180003C8
write_lag |
flush_lag |
replay_lag |
sync_priority | 0
sync_state | async --异步

方法3.根据PG进程

进程中显示wal sender的是主库,显示wal receiver的是备库,如下:
主库

[root@slave 11]# ps -ef|grep walsender
postgres 8625 8612 0 03:26 ? 00:00:00 postgres: walsender repuser 192.168.20.133(55306) streaming 0/1E0001B0
root 9404 3073 0 03:40 pts/0 00:00:00 grep --color=auto walsende

备库

[root@master data]# ps -ef|grep walreceiver
postgres 4306 4079 0 03:26 ? 00:00:01 postgres: walreceiver streaming 0/1E0001B0
root 4360 1392 0 03:41 pts/0 00:00:00 grep --color=auto walreceiver

方法4.通过pg_is_in_recovery函数

备库是t,主库是f。
主库

postgres=# select pg_is_in_recovery();
pg_is_in_recovery
-------------------
f
(1 row)

备库

postgres=# select pg_is_in_recovery();
pg_is_in_recovery
-------------------
t
(1 row)