PostgreSQL复制方式有两种:物理复制和逻辑复制。
早在PG9.0版本开始支持物理复制,也可以叫流复制(Streaming Replication下文中流复制一般指物理流复制)。PG10版本开始支持逻辑复制。
流复制技术可以在实例级别复制出一个与主库一模一样的从库(备库)。通过流复制,备库不断的从主库同步相应的数据,并在备库apply每个WAL record,这里的流复制每次传输单位是WAL日志的record。而PostgreSQL9.0之前提供的方法是主库写完一个WAL日志文件后,才把WAL日志文件传送到备库,这样的方式导致主备延迟比较大,大概是一个WAL日志文件的大小。PostgreSQL9.0之后还提供了Hot Standby功能,备库在应用WAL record的同时也能够提供只读服务,自此PostgreSQL可以支持读写分离。
逻辑复制通常也称之为选择性复制,他可以做到基于表级别的复制,选择需要逻辑复制的表。
流复制和逻辑复制的区别:

逻辑复制核心原理虽然也基于WAL但稍有不同。逻辑复制会根据预先设置好的规则解析WAL日志,将WAL二进制文件解析成一定格式的逻辑变化信息,主库将逻辑变化信息发送给备库,备库接收到WAL逻辑解析信息后再应用。
对于流复制和逻辑复制而言,两者可应用于不同的场景
本系列文章将主要分为以下7个章节介绍:
1. 流复制部署(异步、同步)
2. 流复制监控
3. 流复制主备切换
4. 延迟备库
5. 同步复制优选提交
6. 级联复制
7. 流复制维护生产案例
流复制部署
实验环境:
部署过程如下,主备节点都需要进行操作:
创建用户:
# groupadd postgres --创建用户组
# useradd postgres -g postgres --创建用户
# passwd postgres --设置postgres用户的密码
创建目录并赋予权限
# mkdir -p data/postgres/11/
# chown -R postgres:postgres data/postgres/11/
解压软件并安装:
# tar -zxvf postgresql-11.1.tar.gz
# cd postgresql-11.1
# ./configure –prefix=/data/postgres/11/
安装依赖包:
# yum install zlib readline
# gmake world
# gmake install-world
初始化数据库:
# su – postgres
备库不需要初始化数据库数据目录,以下参数的修改均在主库执行:
$ initdb -D data/postgres/11/data -E UTF8 –locale=C -U postgres
-- 指定数据库数据目录, -E 指定字符集 -locale 指定区域偏好
数据库安装完成后,需要配置如下所示数据库参数:

以上为流复制配置过程中主要的参数,除此以外配置主库的pg_hba.conf:
#replication privilege
hots replication repuser 192.168.80.126/32 md5
hots replication repuser 192.168.80.127/32 md5
启动pghost1上的数据库:
$ pg_ctl start
使用超级用户postgres登录到数据库创建流复制用户repuser,流复制用户需要有replication和login权限,该部分建议新建流复制专用用户而不是使用超级用户:
create user replica replication login connection limit 5 encrypted password 'replica';
在pghost2以pg_basebackup命令部署流复制:
$ pg_basebackup -D data/postgres/11 -Fp -Xs -v -P -h 192.168.80.126 -p 5432 -U repuser
pg_basebackup命令执行的操作为将主库的数据目录同步到备节点,保证主备数据目录保持一致。
进入数据库数据目录下,新建recovery.conf文件并配置以下参数:
recovery_target_timeline = 'latest'
standby_mode = on
primary_conninfo = 'host=192.168.80.126 port=5432 user=repuser'
recovery_target_timeline
设置恢复的时间线,latest表示从备份中恢复到最近的时间线
standby_mode
设置是否启用数据库为备库,如果设置为on,备库会不停的从主库上获取WAL日志流,直到获取主库上最新的WAL日志流。
primary_conninfo
参数设置主库的连接信息,设置了主库IP、端口、用户名信息,但没有配置明文密码,在连接串中给出数据库密码不是好习惯,建议将密码配置在隐藏文件~/.pgpass 中。
$ touch ~/.pgpass
$ chmod 0600 ~/.pgpass
.pgpass文件内容分为五部分,分别为:
IP:端口号:数据库名:用户名:密码
192.168.80.126:5432:replication:repuser:repuser
192.168.80.127:5432:replication:repuser:repuser
流复制部署完成后,可通过pg_stat_replication试图的sync_state字段查看流复制状态:
postgres=# select usename,application_name,client_addr,sync_state from pg_stat_replication;
usename | application_name | client_addr | sync_state
-----------+--------------------+-----------------+------------
repuser | walreceiver | 192.168.80.127 | async
(1 row)
sync_state字段的可选项包括:
async:表示备库为异步同步模式
sync:当前备库为同步模式
potential:表示备库当前为异步同步模式,如果当前的同步备库宕机后,异步备库可升级成为同步备库。
quorum:表示备库为quorum standbys的候选,后面会介绍这个特性。
同步流复制
前面我们搭建的环境为异步流复制,异步流复制指主库上提交事务时不需要等待备库接收并写入WAL日志就返回成功,如果主库异常宕机,主库上提交的事务可能还没来得及发送给备库,就会造成备库数据丢失。
同步流复制在主库上提交事务时需要等待备库接收并写入WAL日志,当主库至少收到一个备库发回的确认信息时便返回成功,同步流复制确保了至少一个备库收到了主库发送的WAL日志,一方面保障了数据的完整性,另一方面增加了事务响应时间。
介绍同步流复制前先介绍一下参数synchronous_commit,理解它的含义能更好的理解同步流复制。
单实例环境:
流复制环境:

备库的recovery.conf配置文件设置如下:
primary_conninfo = 'host=192.168.80.126' port=5432 user=repuser application_name=node2'
primary_conninfo参数添加application_name选项,application_name选项指定备节点的别名,主库postgresql.conf的synchronous_standby_names可引用备库application_name选项设置的值,设置成node2。
主库上postgresql.conf配置文件设置为以下参数,其他参数与异步流复制配置一致。
synchronous_commit = on或者remote_apply
synchronous_standby_names = 'node2'
主库查看复制状态,如下所示:







