PostgreSQL13主从同步异步流复制
介绍
PostgreSQL早在9.0版本开始支持物理复制,也可称为流复制( Streaming Replication,通过流复制技术,可以从实例级复制出一个与主库一模一样的从库 (也称之为备库)。举个简单的例子,在主机pghost1上创建了一个PostgreSQL实例,并在实例上创建多个数据库,通过流复制技术可以在另外一台主机如pghost2上创建一个热备只读PosgreSQL实例,我们通常将pghost1上的数据库称为主库(Primary Database或Master), pghost2 上的数据库称为备库(Standby Database或Slave), pghostl1 称为主节点,pghost2 称为备节点。流复制同步方式有同步、异步两种,如果主节点和备节点不是很忙,通常异步模式下备库和主库的延迟时间能控制在毫秒级。
流复制根据同步方式分为异步流复制和同步流复制,异步流复制是指主库上提交事务时不需要等待备库接收WAL日志流并写入到备库WAL日志文件时便返回成功,而同步流复制相反。
接下来介绍的流复制是基于异步流复制的,使用pg_basebackup方式部署。
pg_basebackup工具是对数据库实例级进行的备份,因此这个工具通常作为备份工具对据库进行基准备份。
pg_basebackup工具发起备份需要超级用户权限或REPLICATION权限,注意max_wal_senders 参数配置,因为pg_basebackup工具将消耗至少一个WAL发送进程。如果从库之前有过数据库只要先停备库之后删除备库数据库数据文件即可。
操作
数据库备份
主库在操作前先将数据库备份,以免在操作过程中出现失误,误删数据库等
./pg_dump -p 11001 -U postgres jssc_data_base > /usr/local/data/pgdata/jssc_data_base.backup
主库创建流复制的用户
CREATE ROLE replica login replication encrypted password '123456';
主库修改pg_hba.conf文件
允许备库IP通过复制用户访问数据库
[postgres@pgprimary data]$ vim pg_hba.conf# "local" is for Unix domain socket connections onlylocal all all md5# IPv4 local connections:host all all 127.0.0.1/32 scram-sha-256# IPv6 local connections:host all all ::1/128 scram-sha-256host all all 0.0.0.0/0 md5# Allow replication connections from localhost, by a user with the# replication privilege.local replicationall md5host replicationall 127.0.0.1/32 scram-sha-256host replicationall ::1/128 scram-sha-256host replicationall 0.0.0.0/0scram-sha-256
最后一行,添加了replica用户可以从任意ip访问主库。
从库上执行对于主库的基础备份
创建数据目录
su postgresmkdir /home/data/pgdata
进入postgres的bin目录下执行pg_basebackup命令
pg_basebackup -h 192.168.1.1 -p 5432 -U replica --password -X stream -Fp --progress -D /home/data/pgdata -R
注意,备份选项上带有-R选项。
等待数据库文件同步完成,完成后可以看到文件以及文件夹全部同步过来了
分析
从以上日志信息看出pg_basebackup命令首先对数据库做一 次checkpoint,之后基于时间点做一个全库基准备份,全备过程中会拷贝$PGDATA数据文件和表空间文件到备库节点对应目录,pg_basebackup主要选项解释如下:
-D:参数表示指定备节点用来接收主库数据的目标路径,可以和主库不一样。
-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_kee _segments参数需要设置得较大,以免备份过程中产生的WAL还没发送到备节点之前被主库覆盖掉,如果出现这种情况创建基准备份将会失败,f(fetch) 方式下主库将会启动一个基准备份WAL发送进程; s(stream) 方式中主库上除了启动一个基准备份WAL发送进程外还会额外启动一个WAL发送进程用于发送主库产生的WAL增量日志流,这种方式避免了ffetch) 方式过程中主库的WAL被覆盖掉的情况,生产环境流复制部署推荐这种方式,特别是比较繁忙的库或者是大库。
-v:参数表示启用verbose模式,命令执行过程中打印出各阶段的日志,建议启用此参数,了解命令执行到哪个阶段。
-P:参数显示数据文件、表空间文件近似传输百分比,由于执行Pg bascbackup 命令过程中主库数据文件会变化,因此这只是一个估算值: 建议启用此选项,了解数据复制的进度。
启动数据库
修改初始化数据路径
这里使用systemctl :
systemctl edit postgresql-13.service
在新空白页覆盖原服务配置
[Service]Environment=PGDATA=/home/data/pgdata
初始化
/usr/pgsql-13/bin/postgresql-13-setup initdb
启动
systemctl start postgresql-13
如果出现以下权限问题
systemctl status postgresql-13.service
解决方法
chmod 700 -R /home/data/pgdata# 设置用户chown -R postgres pgdata
查看配置文件
可以看到备库服务器上自动生成了standby.signal文件。同时,也看到在$PGDATA路径下,数据库自动帮我们配置了关于流复制的主库的信息:
cat postgresql.auto.conf
如果我们没有使用-R来备份主库的话。我们完全可以在备库上手工创建standby.signal文件,然后手工编辑postgresql.auto.conf,并在其内容中配置主库的信息。
primary_conninfo = 'user=replica password=123456 channel_binding=disable host=192.168.1.1 port=5432 sslmode=disable sslcompression=0 ssl_min_protocol_version=TLSv1.2 gssencmode=disable krbsrvname=postgres target_session_attrs=any'
查看相关进程
查看从库进程信息
ps -ef|grep postgres
备库上,可以看到walreceiver进程,正在读取日志streaming 0/230454C0,执行恢复recovering 000000010000000000000023。
查看主库进程信息
ps -ef|grep postgres
主库上看到,后台进程walsender,正在向replica 1180.110.177.72(19333) streaming 0/230454C0推送日志信息。
查看流复制同步方式
异步流复制部署完成后,可通过pg_statZ_replication系统视图的sync_state字段查看流复制同步方式
SELECT usename,application_name,client_addr,sync_state FROM pg_stat_replication;
pg_stat_replication视图显示主库上WAL发送进程信息,主库上有多少个WAL发送进程,此视图就对应多少条记录,这里主要看sync_state 字段,syne_state 字段的可选项包括:
async:表示备库为异步同步方式。
potential: 表示备库当前为异步同步方式,如果当前的同步备库宕机后,异步备库可升级成为同步备库。
sync: 当前备库为同步方式。
quorum:此特性为PostgreSQL10版本新增特性,表示备库为quorum standbys的候选。
以上查询结果sync_state 字段值为async,表示主备数据复制使用异步方式。
测试
使用pgadmin查看从库可以发现,数据库结构和主库是一样的
在主库某个数据库表中插入一条数据,从库中对应的表也会生成一条记录
参考
参考文档