PostgreSQL 早在9.0版本开始支持物理复制,也可称为流复制( Streaming Replication ),通过流复制技术,可以从实例级复制出一个与主库一模一样的从库(也称之为备库) 举个简单的例子,在主机 host1 上创建了一个 PostgreSQL 实例,并在实例上创建多个数据库,通过流复制技术可以在另外一台主机 host2 上创建个热备只读 PostgreSQL实例,我们通常将 host1 上的数据库称为主库( Primary Database 或Master) ,host2 上的数据库称为备库( Standby Database或Slave),host1 称为 主节点, host2 称为备节。流复制同步方式有同步、异步两种,如果主节点和备节点不是很忙,通常异步模式下备库和主库的延迟时间能控制在毫秒级。
WAL (Write-Ahead Logging )日志记录数据库的变化,格式为二进制格式,当主机出现异常断电时,如果 WAL 文件已经写入成功,但还没来得及刷新数据文件,当数据库再次启动时会根据 WAL 日志文件信息进行事务前滚,从而恢复数据库到一致性状态。
1 异步流复制
流复制根据数据同步方式分为异步流复和同步流复 ,异步流复制是指主库上提交事务不需要等待备库接收 WAL 日志流并写入到备库 WAL 志文件时便返回成功,而同步流复制相反,后面会详细介绍异步流复制、同步流复制的部署。
这一小节先介绍 PostgreSQL 异步流复制的部署,异步流复制部署主要有两种方式,一方式是拷贝数据文件方式,另一种方式是通过pg_basebackup命令行工具 这两种方式绝大部分部署步骤都一样,只是数据复制的方式不同而己,接下来会详细介绍实验环境为两台虚拟机,具体信息如表 1-1
主机 | 主机名 | IP地址 | 操作系统 | PostgreSQL版本 |
---|---|---|---|---|
主节点 | host1 | 192.168.137.129 | CentOS 7 | PostgreSQL10 |
备节点 | host2 | 192.168.137.130 | CentOS 7 | PostgreSQL10 |
1.1 以拷贝数据文件方式部署流复制
在主备 host1和 host2 上创建操作系统用户和相关目录,如下所示:
groupadd postgres
useradd pg10 -g postgres
passwd pg10
mkdir -p /home/pg10/postgresql10.23/data
mkdir -p /home/pg10/postgresql10.23/tbl
chown -R pg10:postgres /home/pg10/postgresql10.23
/home/pg10/postgresql10.23/data 目录存储数据库系统数据文件,/home/pg10/postgresql10.23/tbl存储用户自定义表空间文件
设置 pg10 操作系统用户环境变量,/home/pg10/.bash_profile 文件添加以下内容:
export PGPORT=1921
export PGHOME=/home/pg10/postgresql10.23
export PGDATA=$PGHOME/data
export PATH=$PATH:$PGHOME/bin
export LD_LIBRARY_PATH=$PGHOME/lib:$LD_LIBRARY_PATH
alias rm='rm -i'
alias ll='ls -lh'
以上内容可根据使用偏好设置环境变量。
主备下载、解压并编译 PostgreSQL 软件,如下所示:
wget https://ftp.postgresql.org/pub/source/v10.23/postgresql-10.23.tar.gz
tar -xf postgresql-10.23.tar.gz -C /home/pg10/
cd /home/pg10/postgresql-10.23
./configure --prefix=/home/pg10/postgresql10.23 --with-pgport=1921 --with-openssl
如果configure过程中缺少如下操作系统包,通过yum install命令安装相关依赖包即可。
-
configure: error: no acceptable C compiler found in $PATH
yum -y install gcc
-
configure: error: readline library not found
yum -y install readline-devel
-
configure: error: zlib library not found
yum -y install zlib-devel
-
configure: error: library ‘crypto’ is required for OpenSSL
yum -y install openssl-devel
之后进行编译安装,如下所示:
gmake world
gmake install-world
chown -R pg10:postgres /home/pg10
gmake world 表示编译所有能编译的东西,包括文档和附加模块 ,而 gmake 命令不会安装这些内容, gmake world 相比 gmake 编译时间长很多。之后通过 gmake install-world命令安装 PostgreSQL 软件到目录/home/pg10/postgresql10.23 ,安装后/home/pg10/postgresql10.23/share 目录下生成 /doc 文档目录,并且 /home/pg10/postgresql10.23/share/extension 目录下生成了大量的扩展模块文件,这些扩展模块提供的功能能够丰富 PostgreSQL 特性,在生产环境下推荐 gmake world 编译安装。
xxxxxxxxxx from selenium import webdriverfrom selenium.common.exceptions import TimeoutException,NoSuchElementExceptionbrowser = webdriver.Chrome()try: browser.get('https://www.baidu.com')except TimeoutException: print('Time Out')try: browser.find_element_by_id('hello')except NoSuchElementException: print('No Element')finally: browser.close()python
su - pg10
initdb -D /home/pg10/postgresql10.23/data -E UTF8 --locale=C -U pg10 -W
以上初始化数据库后,目录下将产生系统数据文件,之后配置,设置以下参数:
listen_addresses = '*' # what IP address(es) to listen on;
wal_level = replica # minimal, replica, or logical
archive_mode = on # enables archiving; off, on, or always
archive_command = 'test ! -f /home/pg10/postgresql10.23/archive/%f && cp %p /home/pg10/postgresql10.23/archive/%f' # command to use to archive a logfile segment
max_wal_senders = 10 # max number of walsender processes
wal_keep_segments = 16 # in logfile segments, 16MB each; 0 disables
hot_standby = on # "off" disallows queries during recovery
以上几个 postgresql.conf 参数是流复制的主要参数,其他可选参数没有列出。
wal_level 参数控制 WAL 日志信息的输出级别,有 minimal、 replica、logical 三种模式, minimal 记录的 WAL 志信息最少,除了记录数据库异常关闭需要恢复时的WAL 信息外,其他操作信息都不记录; replica 记录的 WAL 信息比 minimal 信息多些,会记录支持 WAL 归档、复制和备库中启用只读查询等操作所 WAL 信息;logical 记录的 WAL 日志信息最多, 包含了支持逻辑解析 (10 版本的新特性,逻辑复制使用这种模式)所需的 WAL ; replica 模式记录的 WAL 信息包含了 minimal 的信息, logical 模式记录的 WAL 信息包含了 replica 记录的信息, 参数默认值为 replica ,调整此参数需重启数据库生效,开启流复制至少需要设置此参数为 replica 级别。
archive_mode 参数控制是否启用归档, off 表示不启用归档, on 表示启用归档并使用 archive command 参数的配置命令将 WAL 日志归档到归档存储上,此参数设置后需重启数据库生效,这里通常设置成 on。
archive_command 参数设置 WAL 归档命令, 可以将 WAL 归档到本机目录,也可以归档到远程主机上,由于流复制的配置并不一 需要依赖配置归档命令,我们将归档命令暂且设置成伪归档命令$PGHOME/archive,后期如果需要打开归档直接配置归档命令即可。
max_wal_senders 参数控制主库上的最大 WAL 发送进程数 ,通 pg_base_backup 命令在主库上做基准备份时也会消耗 WAL 进程,参数设置不能比 max_connections参数值高,默认值为 10,一个流复制备库通常只需要消耗流复制主库 WAL 发送进程。
wal_keep_segments 参数设置主库 pg_wal 目录保留的最小 WAL 日志文件数,以便备库落后主库时可以通过主库保留的 WAL 进行追回,这个参数设置得越大,理论上备库在异常断开时追平主库的机率越大,如果归档存储空间充足,建议将此参数配置得大些,由于默认情况下每个 WAL 文件为 16MB (编译时可通过 with-wal-segsize 参数设 WAL 文件大小),因此 pg_wal 目录大概占用空间为 wal_keep_segments 参数值× 16MB ,这里为 16×16MB=256MB ,实际情况下 pg_wal 目录下的WAL 文件数会比此参数的值稍大些。
hot_standby 参数控制数据库恢复过程中是否启用读操作 ,这个参数通常用在流复制备库,开启此参数后流复制备库支持只读 SQL ,但备库不支持写操作,主库上也设参数为on。
以上是流复制配置过程中主要的 postgresqI.conf 参数,其他参数没有列出,主库和备库的 postgresqI.conf 配置建议完全一致。
配置主库的 pg_hba.conf 文件,添加以下内容:
# replication privilege.
host replication repuser 192.168.137.129/32 md5
host replication repuser 192.168.137.130/32 md5
这里为什么配置两条 pg_hba.conf 策略?因为主库和备库的角色不是静止的,它们的角色是可以互换的,比如做一次主备切换后角色就发生了变化,因此建议主库、备库 pg_hba.conf 配置完全一致。
之后 host1 启动数据库,如下所示:
pg_ctl start
使用超级用户 pg10 登录到数据库创建流复制用户 repuser ,流复制用户需要有 REPLICATION 权限和 LOGIN 权限,如下所示:
psql -d postgres
CREATE USER repuser REPLICATION LOGIN CONNECTION LIMIT 5 ENCRYPTED PASSWORD 're123456';
建议为流复制创建专门的流复制用户。
以上完成了主库上的配置,接下来热备生成一个备库,制作备库过程中主库仍然可读写,不影响主库上的业务,以 pg10 超级用户执行以下命令:
postgres=# SELECT pg_start_backup('label1');
pg_start_backup
-----------------
0/2000060
(1 row)
pg_ start_ backup() 函数在主库上发起一个在线备份,命令执行成功后,将数据文件拷贝到备节点 host2,如下所示。
tar -cf data.tar.gz data --exclude=data/pg_wal
scp data.tar.gz 192.168.137.130:/home/pg10/postgresql10.23
pg_wal 目录不是必须复制的,如果 pg_wal 目录下文件较多,压缩包时可以排除这个目录, 节省数据拷贝时间,数据到备节点后,备节点 pg_wal 目录需要手工创建,以上只是拷 data 系统数据目录, 如果有另外的表空间目录也需要拷贝。
之后在 host2 解压文件,如下所
tar -xf data.tar.gz
mkdir data/pg_wal
文件拷贝到备节点后,在主库执行以下命令:
postgres=# SELECT pg_stop_backup();
NOTICE: pg_stop_backup complete, all required WAL segments have been archived
pg_stop_backup
----------------
0/A000130
(1 row)
以上命令表示完成在线备份,但备库上仍然需要一些配置, 之后配置host2主机上的recovery.conf,此配置文件提供了数据库恢复相关的配置参数,这个文件默认在$PG_DATA 并不存在, 可以在软件目录中找,并复制到 $PGDATA目录如下所示:
cp $PGHOME/share/recovery.conf.sample $PGDATA/recovery.conf
在recovery.conf中配置以下参数
recovery_target_timeline = 'latest'
standby_mode = on
primary_conninfo = 'host=192.168.137.129 port=1921 user=repuser'
recovery_target_timeline 参数设置恢复的时间线(timeline)默认情况下是恢复到基准备份生成时的时间线,设置成 latest 表示从备份中恢复到最新的时间线,通常复制环境设置此参数为 latest ,复杂的恢复场景可将此参数设置成其他值。
standby_mode 参数设置是否启用数据库为备库,如果设置 on ,备库会不停地从主库获取 WAL 日志流,直到主库上获取主库上最新的 WAL 日志流。
primary_conninfo 参数设置主库的连接信息 ,这里设置了主库 IP、端口、用户名信息,但没有配置明文密码,在连接串中给出数据库密码不是好习惯, 建议将密码配置在隐藏文件~/.pgpass文件中。
配置~/.pgpass隐藏文件,如下所示:
touch .pgpass
chmod 0600 .pgpass
.pgpass 文件默认情况下不存在,需要手动创建并设置 0600 后给 .pgpass权限。之后给.pgpass文件添加以下内容:
192.168.137.129:1921:replication:repuser:123456
192.168.137.130:1921:replication:repuser:123456
.pgpass文件内容分五个部分,分别为IP、端口、数据库名、用户名、密码,用冒号分割,设置后,repuser用户可以免密码直接登录到数据库。之后在host2上启动从库即可,如下所示:
pg_ctl start
如果此步没报错,并且主库上可以查看到 WAL 发送进程,同时备库上可以看到 WAL 接收进程说明流复制配置成功,查看主库上的 WAL 发送进程 如下所示:
postgres: wal sender process repuser 192.168.137.130(56102) streaming 0/13000060
查看备库上的 WAL 接收进程,如下所示:
postgres: wal receiver process streaming 0/13000060
接着在主库上创建一个测试表并插入数据,如下所示:
postgres=# create table test(id int);
CREATE TABLE
postgres=# insert into test values(1);
INSERT 0 1
在备库上验证数据是否已同步,如下所示:
postgres=# select * from test;
id
----
1
(1 row)
在主库上创建一张表后,在备库上立刻就能查询到了,值得一提的是,备库上 postgresql.confd 的 hot_standby 参数需要设置成 on 才支持查询操作,此参数调整后需重启数据库生效,如下所示:
hot_standby = on # "off" disallows queries during recovery
参数设置成 off ,通过 psql 连接数据库时会抛出以下错误
$ psql postgres
2023-02-08 22:47:31.838 CST [12048] FATAL: the database system is starting up
psql: FATAL: the database system is starting up
以上信息显示数据库在恢复中,不允许连接数据库也不允许执行查询。
以上是异步流复制部署的所有过程,虽然本小节内容有些多,但总体来说流复制配置并不复杂,读者在配置过程中如遇错误,根据数据库日志报错信息进行问题排查。
1.2 以pg_basebackup方式部署流复制
上一小节介绍了以拷贝数据文件的方式部署流复制,这一 小节介绍 pg_basebackup 方式部署流复制,通过上一小节的介绍,部署流复制备库的数据复制环节主要包含三个步骤:
- 执行SELECT pg_start_backup('label1');
- 拷贝主节点 PGDATA 数据文件和表空间文件到备节点;
- 执行pg_stop_backup();
以三个步骤可以合成一步完成, PostgreSQL 提供内 pg_basebackup 命令行工具支持对主库发起一个在线基准备份,并自动进入备份模式进行数据库基准备份,备份完成后自动从备份模式退出,不需要执行额外的 pg_start_backup() 和 pg_stop_backup() 命令显式地声明进入备份模式和退出备份模式,pg_basebackup 工具是对数据库实例级进行的物理备份,因此这个工具通常作为备份工具对据库进行基准备份。
pg_basebackup 工具发起备份需要超级用户权限或 REPLICATION 权限, 注意 max_wal_senders 参数配置,因为 pg_basebackup 工具将消耗至少一个 WAL 发送进程。本节将演示通过 pg_basebackup 工具部署异步流复制,之前已经在 host2 上部署了一个备库 ,我们先将这个备库删除,之后通过 pg_basebackup 工具重新做一次备库,删除 host2 上的备库只需要先停备库之后删除备库数据库数据文件即可,如下所示:
pg_ctl stop
rm -rf /home/pg10/postgresql10.23/data
之后在 host2 使用 pg_basebackup 工具做一个基准备份,如下所示:
$ pg_basebackup -D /home/pg10/postgresql10.23/data -Fp -Xs -v -P -h 192.168.137.129 -p 1921 -U repuser
pg_basebackup: initiating base backup, waiting for checkpoint to complete
pg_basebackup: checkpoint completed
pg_basebackup: write-ahead log start point: 0/14000028 on timeline 1
pg_basebackup: starting background WAL receiver
23749/23749 kB (100%), 1/1 tablespace
pg_basebackup: write-ahead log end point: 0/140000F8
pg_basebackup: waiting for background process to finish streaming ...
pg_basebackup: base backup completed
从以上日志信息可以看出 pg_basebackup 命令首先对数据库做一次 checkpoint ,之后基于时间点做一个全库基准备份, 全备过程中会拷贝 $PGDATA 数据文件和表空间文件到备库节点对应目录, pg_basebackup 主要选项解释如下:
-D 参数表示指定备节点用来接收主库数据的目标路径,这里和主库保持一致,依然是 /home/pg10/postgresql10.23/data 目录。
-F 参数指定 pg_basebackup 命令生成的备份数据格式,支持两种格式, p(plain)格式和 t(tar)格式, p(plain )格式是指生成的备份数据和主库上的数据文件布局一样,也就是说类似于操作系统命令将数据库 $PGDATA 系统数据文件、表空间文件完全拷贝到备节点; t(tar)格式是指将备份文件打个 tar 包并存储在指定目录里,系统文件被打包成 base.tar ,其他表空间文件被打包成 oid.tar,其中 OID 为表 间的 OID。
-X 参数设置在备份的过程中产生的 WAL 日志包含在备份中的方式,有两种可选方式, f(fetch )和 s(stream), f(fetch)是指 WAL 日志在基准备份完成后被传送到备节点,这时主库上的 wal_keep_segments 参数需要设置得较大, 以免备份过程中产生WAL 还没发送到备节点之前被主库覆盖掉,如果出现这种情况创建基准备份将会失败, f(fetch) 方式下主库将会启动一个基准备份 WAL 发送进程; s(stream )方式中主库上除了启动一个基准备份 WAL 发送进程外还会额外启动一个 WAL 发送进程用于发送主库产生的 WAL 增量日志流,这种方式避免了f(fetch)方式过程中主库WAL 被覆盖掉的情况,生产环境流复制部署推荐这种方式,特别是比较繁忙的库或者是大库。
-v 参数表示启用 verbose 模式,命令执行过程中打印出各阶段的日志,建议启用此参数,了解命令执行到哪个阶段。
-P 参数显示数据文件、表空间文件近似传输百分比,由于执行 pg_basebackup 过程中主库数据文件会变化,因此这只是一个估算值;建议启用此选项,了解数据复制的进度。
-h、-p、-U 参数为数据库连接通用参数,不再解释,以上只是 pg_basebackup 命令主要选项,其他选项读者可查看手册 https://www.postgresql.org/docs/10/app-pgbasebackup.html
命令执行成功后,配置备库 recovery.conf ,之前已将此文件备份到家目录,从家目录将此文件复制到 $PGDATA 目录下即可 ,如下所示:
cp ~/recovery.conf $PGDATA
之后在 host2 上启动备库,如下所示:
pg_ctl start
这时备节点上已经有了 WAL 接收进程,同时主节点上已经有了 WAL 发送进程,表示流复制工作正常。
1.3 查看流复制同步方式
异步流复制部署完成后,可通过 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.137.130 | async
(1 row)
pg_stat_replication 视图显示主库上 WAL 发送进程信息,主库上有多少个 WAL 发送进程, 此视图就对应多少条记录 ,这里主要看 sync_state 字段, sync_state 字段的可选项包括:
- async:表示备库为异步同步方式。
- potential:表示备库当前为异步同步方式,如果当前的同步备库岩机后,异步备库可升级成为同步备库。
- sync:当前备库为同步方式。
- quorum :此特性为 PostgreSQL 10 版本新增特性,表示备库 quorum standbys 的候选。
以上查询结果 sync_state 字段值为 async,表示主备数据复制使用异步方式。
2 同步流复制
异步流复制指主库上提交事务时不需要等待备库接收并写入 WAL 日志时便返回成功,如果主库异常宕机,主库上已提交的事务可能还没来得及发送给备库,就会造成备库数据丢失,备库丢失的数据量和 WAL 复制延迟有关, WAL 制延迟越大,备库上丢失的数据量越大。
同步流复制在主库上提交事务时需等待备库接收WAL ,当主库至少收到一个备库发回的确认信息时便返回成功,同步流复制确保了至少一个备库收到了主库发送的 WAL 日志,一方面保障了数据的完整性,另一方面增加了事务响应时间,因此同步流复制主库的吞吐量相比异步流复制主库吞吐量低。
这一小节将介绍同步流复制的部署, 同步流复制的部署与异步流复制部署过程没有太大差 ,只是postgresql.,conf和recovery.conf 配置文件的几个参数需要额外配置。
2.1 synchronous_commit 参数详解
在介绍同步流复制部署之前先来介绍 synchronous_commit 参数, synchronous commit 参数是流复制配置中的重点参数,理解它 含义能够更好地理 同步流复制 、异步流复的工作原理。
synchronous_commit 参数是 postgresqI.conf 配置文件中 WAL 相关配置参数,是指当数据库提交事务时是否需要等待 WAL 日志写人硬盘后才向客户端返回成功 ,此参数可选值为on、off、local、remote_ apply、remote_write ,要理解每个参数的含义可能没那么容易 ,这里尽可能详细解释这些选项值的含义,分单实例和流 制环境介绍。
场景一:单实例环境
on:当数据库提交事务时, WAL 先写人 WAL BUFFER 再写入 WAL 日志文件,设置成 on 表示提交事务时需等待本 WAL 写人 WAL 日志后才向客户端返回成功,设置成 on 非常安全,但数据库性能有损耗。
off:设置成 off 表示提交事务时不需等待本地 WAL BUFFER 写入 WAL 日志后向客户端返回成功,设置成 off 时也不会对数据库带来风险,虽然当数据库着机时最新提交的少量事务可能丢失,但数据库重启后会认为这些事务异常中止,设置 off 能够提升数据库性能,因此对于数据准确性没有非常精确要求同时追求数据库性能的场景建议设置成 off。
loca:local 含义和 on 类似,表示提交事务时需等待本地 WAL 写入后才向客户端返回成功。
场景二:流复制环境
remot_write:当流复制主库提交事务时,需等待备库接收主库发送的 WAL 日志流并写入备节点操作系统缓存中,之后向客户端返回成功,这种情况下备库实例出现异常关闭时不会有已传送的 WAL 日志丢失风险,但备库操作系统异常看宕机就有已传送的 WAL 丢失风险了,此时 WAL 可能还没完全写人备节点 WAL 文件中,简单地说 remot_write 表示本地 WAL 已落盘,备库的 WAL 还在备库操作系统缓存中,也就是说只有一份持久化的 WAL ,这个选项带来的事务响应时间较低。
on:设置成 表示流复制主库提交事务时, 等待备库接收主库发送的 WAL 日志流并写人 WAL 文件,之后才向客户端返回成功,简单地说 on 表示本地 WAL 已落盘,备库的 WAL 也已落盘, 也就是说有两份持久化的 WAL ,但备库此时还没有完成重做,这个选项带来的事务响应时间较高。
remote_apply:表示流复制主库提交事务时 ,需等待备库接收主库发送的 WAL 并写人 WAL 文件,同时备库已经完成重做,之后才向客户端返回成功,简单地说 remote_apply 表示本 WAL 已落盘,备库 WAL 已落盘并且已完成重做,这个设置保证了拥有两份持久化的 WAL ,同时备库也完成了重做,这个选项带来的事务响应时间最高。
2.2 配置同步流复制
备库 recovery. conf 配置文件设置以下参数,如下所示:
primary_conninfo = 'host=192.168.137.129 port=1921 user=repuser application_name=node2'
primary_conninfo 参数添加 appication_name 选项, appication_name 选项指定备节点的别名,主库 postgresql.conf的synchronous_standby_names 参数可引用备库 application_name 选项设置的值,这里设置成 node2。
主库上 postgresql.conf 置文件设置以下参数, 其他参数和异步流复制配置一致。
synchronous_commit = on # synchronization level;
synchronous_standby_names = 'node2' # standby servers that provide sync rep
wa_level 配置也和异步流复制配置一致,设置 replica或logical 即可。
synchronous_commit 参数配置成 on 或 remote_apply ,通常设 on 表示有两持久化的 WAL 日志。
synchronous_standby_names 参数配置同步复制的备库列表,可以配置多个同步备库,实验环境为一主一备环境,因此这里设 node2 ,这个值必须和同步备库 recovery.conf 文件的 primary_conninfo 参数 application_name 选项设置值一致。
配置完成后,主库执行以下命 使配置生效:
pg_ctl reload
wa_level 参数调整后需重启数据库生效, synchronous_commit 和 synchronous_standby_names 参数调整后不需要重启数据库生效,只需执行 pg_ctl reload 命令重新载入配置文件即可。由于配置异步流复制时 wa_level 已经配置成 replica ,因此不需要再调整此参数配置。
备库调整了 recovery.conf 参数后需重启生效, host2 上重启数据库,如下所示:
pg_ctl restart
之后查看主库是否建立了 WAL 发送进程,备库上是否建立了 WAL 接收进程, 如果有异常,查看数据库日志排查错误。
主库上查看复制状态,如下所示
postgres=# select usename,application_name,client_addr,sync_state from pg_stat_replication;
usename | application_name | client_addr | sync_state
---------+------------------+-----------------+------------
repuser | node2 | 192.168.137.130 | sync
(1 row)
此时 pg_stat_replication 图的 sync_state 字段已变成了 sync 状态,sync 表示主库与备库之间采用同步复制方式,以上就是同步流复制主要配置步骤。
2.3 同步流复制的典型“陷阱”
同步流复制模式中,由于主库提交事务时需等待至少一个备库接收 WAL 并返回确认信息后主库才 客户端返回成功, 一方面保障了数据的完整性,另一方面对于一主一备的同步流复制环境存在一个典型的“陷阱”,具体表现为如果备库若机, 主库上的写操作将处于等待状态。接下来在刚部署完成的同步流制环境做个测试,环境为一主一备, host1上的数据库为主库, host2 上的数据库为同步备库。
先把备库停掉模拟备库故障,如下所示:
pg_ctl stop
之后 试在主库上执行读操作,如下所示:
postgres=# select * from test limit 1;
id
----
1
(1 row)
同步备库宕机后 ,主库上的查询不受影响。
之后在主库上尝试插入一条记录,如下所示:
postgres=# insert into test values(1);
--阻塞住
注意这里命令被阻塞。
这时主库上的 INSERT 一直处于等待 ,也就是说同步备库宕机后,主库上的读操作不受影响, 写操作将处于等待状态 ,因为主库上的事务需收到至少一个备库接WAL 后的返回信息才会向客户端返回成功,而此时备库已经停掉了,主库上收不到备库发来的确认信息,如果是生产库, 将对生产系统带来严重影响。
通常生产系统一主一备的情况下不会采用同步复制方式,因为备库若机后同样对生产统造成严重影响,PostgreSQL 支持一主多从的流复制架构,比如一主两从,将其中一个备库设为同步备库,另一个设为异步备库,当同步备库若机后异步备库升级为同步备库, 同时主库上的读写操作不受影响。