当前位置: 首页 > 科技观察

PostgreSQL 12 的同步流复制搭建及主库Hang问题处理与分析_0

时间:2023-03-12 01:23:41 科技观察

PostgreSQL12同步流复制构建及主库Hang问题处理与分析本文转载请联系数据云公众号。前言主从流复制是PostgreSQL高可用和读写分离最常用也是最简单的一种形式。它类似于Oracle的ADG。主库用于读写,备库可以只读。PostgreSQL流复制有两种方式,异步流复制和同步流复制。异步流复制模式下,当备库异常时,主库可以正常读写;在同步流复制模式下,当备库异常时,主库可能会挂掉(DML、DDL)。这两天根据需要需要搭建一个同步流复制库,但是过程中遇到了一些小问题,所以记录下来作为备忘和指导,帮助大家避坑。一、基础环境本次搭建,我的PostgreSQL基础环境如下:PostgreSQL版本为12.5;操作系统为CentOS7.6;PostgreSQL的流复制的核心步骤非常简单,只需要2-3步:1.对源数据库进行基本备份;2.将基本备份复制到目标;3、配置备库参数,启动备库。备份时,我们在目标端直接通过pg_basebackup工具备份源数据库,将数据目录直接放在目标端的/pgdata中:pg_basebackup-h192.168.18.181-p18801-Urepl-lpg_basebackup_`date+%Y%m%d%H%M%S`-Fp-Xfetch-P-v-R-D/pgdata在PostgreSQL12中没有recovery.conf文件,而是被standby.signal文件替代,需要在recovery中.conf文件配置的primary_conninfo参数已经集成到postgresql.conf中。所以,此时我们只需要配置主库和备库的postgresql.conf,以及备库的standby.signal,如下:在备库的standby.signal中:standby_mode='on'主库的postgresql.conf中:#同步流复制synchronous_standby_names='standbydb1'#同步流复制只配置这个值synchronous_commit='remote_write'备库的postgresql.conf中:hot_standby='on'primary_conninfo='application_name=standbydb1user=replpassword=repl123host=192.168。18.181port=18801sslmode=disablesslcompression=0gssencmode=disablekrbsrvname=postgrestarget_session_attrs=any'配置完成后,直接启动备库。pg_ctl-D/pgdatastart3、发现问题通过ps-ef|greppostgres,已经可以看到主库和备库的walsender和walreciver进程已经启动,流复制也已经设置完成。但是通过pg_stat_replication查看后发现,当前数据库状态还是异步流复制状态:postgres=#select*frompg_stat_replication;-[RECORD2]----+------------------------------pid|11767usesysid|24746usename|repapplication_name|walreceiverclient_addr|192.168.18.182client_hostname|client_port|29946backend_start|2021-01-1722:48:36.529698+08backend_xmin|state|streaming|0sent_lsn/91000148write_lsn|0/91000148flush_lsn|0/91000148replay_lsn|0/91000148write_lag|flush_lag|replay_lag|sync_priority|0sync_state|asyncreply_time|2021-01-1722+485:486.5主节点运行time库将挂起。postgres=#insertintowangxin1values(1,'aaa');^CCancelrequestsentWARNING:cancelingwaitforsynchronousreplicationduetousrequestDETAIL:Thetransactionhasalreadycommittedlocally,butmightnothavebeenreplicatedtothestandby.所以一开始一直以为是备库的wal或者disk相关的write配置参数有问题,修改了很多。但是仍然无法将备库的状态改为同步流复制(也尝试多次设置synchronous_commit参数,但只有当参数为local时,主库才不会挂)。4、原因分析经过将近一天的资料查询和官方文档构建标准参数设置方法查询,发现在网上的一些帖子中,需要修改postgresql.auto.conf参数文件。我们知道postgresql.auto.conf参数文件是一个动态参数文件。一般我们不会手动修改,而是在数据库中通过altersystemsetparameter_name=values修改文件中的参数。不过还有一点需要知道的是postgresql.auto.conf的优先级高于postgresql.conf。当我们启动数据库时,postgresql会先加载postgresql.auto.conf中的参数。当没有选择相应的参数时,会加载postgresql.conf中的参数。于是,这时候进入数据库查看primary_conninfo参数:showprimary_conninfoprimary_conninfo|'user=replpassword=repl123host=192.168.18.181port=18801sslmode=disablesslcompression=0gssencmode=disablekrbsrvname=postgrestarget_session_attrs=any'可以从数据库中看到timeprimary_conninfo加载的参数是异步流复制的参数,不是我们在postgresql.conf中配置的同步流复制的参数。此时,我们到postgresql.auto.conf中查看:catpostgresql.auto.conf#Donoteditthisfilemanually!#ItwillbeoverwrittenbytheALTERSYSTEMcommand.primary_conninfo='user=replpassword=repl123host=192.168.18.181port=18801sslmode=disablesslcompression=0gssencmode=disablekrbsrvname=postgrestarget_session_attrs=any'可以看出在postgresql.auto.conf中设置了参数primary_conninfo,它是异步流复制的配置参数。至此,我们就可以了解最初异常的原因了。实际上,在PostgreSQL中通过pg_basebackup进行基本备份时(由于增加了-R参数),默认会在postgresql.auto.conf文件中加入primary_conninfo参数,这个参数是异步流复制的参数(其实我们不能使用postgresql.conf中配置的primary_conninfo参数)。但是,此文件中只有primary_conninfo参数。当我们要将流复制设置为同步方法时,我们必须配置两个参数:synchronous_standby_names和synchronous_commit。当我们在postgresql.conf中设置这两个参数时,由于postgresql.auto.conf中没有,所以只能在这里获取。此时数据库在进行DML和DDL操作时,会等待备库的响应,但是备库是异步流复制,所以不会回复主库已经接收或者写入了wal到磁盘。因此,主库会一直挂掉。五、解决方案解决这个问题,有以下几种方法:1、在备库上,通过命令:altersystemsetprimary_conninfo='application_name=standbydb1user=replpassword=repl123host=192.168.18.181port=18801sslmode=disablesslcompression=0gssencmode=disablekrbsrvname=postsiongrestarget=任何';设置postgresql.auto.conf中的primary_conninfo参数,重启备库。2、手动修改postgresql.auto.conf文件,手动将primary_conninfo参数改为同步流复制参数,重启备库。3.在备用数据库上,通过命令:altersystemsetprimary_conninfo=default;清除postgresql.auto.conf中primary_conninfo参数的配置,重启备库,让数据库识别postgresql.conf文件中的参数。4、手动删除postgresql.auto.conf文件,手动删除或注释primary_conninfo参数,重启备库,让数据库识别postgresql.conf文件中的参数。完毕!