
点击蓝字关注我们
本文介绍 EPAS 16 中的新增加功能“允许从备用服务器进行逻辑复制”。
此功能使用户能够将数据流式传输到其他PostgreSQL 实例,为开发人员提供了新的工作负载分布选项。此外,它还使备用服务器能够将逻辑更改发布到其他服务器。我们可以在备用服务器上设置逻辑复制,这在 16 以下的版本中是无法实现的。这是 PostgreSQL 16 中最有用的功能之一,它增加了从物理复制备用服务器执行逻辑复制的能力。
一、备用服务器设置逻辑复制的示例
在这个示例中,为了简单起见,我们在同一台服务器上运行 3 个 EPAS 实例,分别使用三个不同的端口。也可以使用三台不同的服务器来实现。
主服务器监听端口 5444,数据目录为 data;
备用服务器监听端口 5445,数据目录为 standby_data1,用于流复制;
订阅服务器监听端口 5446,数据目录为 logical_data,用于逻辑复制。
1.1 在主服务器上
在 postgresql.conf 文件中,需要启用以下参数:
$ vim var/lib/edb/as16/data/postgresql.confwal_level = logicalhot_standby = onmax_wal_senders = 10max_replication_slots = 10hot_standby_feedback = on
添加 HBA 规则以允许连接,通过编辑文件 var/lib/edb/as16/data/pg_hba.conf。
重启 Postgres:
$ usr/edb/as16/bin/pg_ctl -D var/lib/edb/as16/data restartwaiting for server to shut down.... doneserver stoppedwaiting for server to start....2024-06-10 00:58:29 PDT LOG: redirecting log output to logging collector process2024-06-10 00:58:29 PDT HINT: Future log output will appear in directory "log".doneserver started
创建两个具有复制权限的用户。一个用于流式传输更改到备用服务器,另一个用于将更改发布到订阅者:
$ /usr/edb/as16/bin/psql -d edbpsql (16.3.0)Type "help" for help.edb=#edb=# create user repuser with replication password 'edb';CREATE ROLEedb=# create user pubuser with replication password 'edb';CREATE ROLEedb=#edb=# \duList of rolesRole name | Attributes-----------------------+--------------------------------------------------aq_administrator_role | No inheritance, Cannot login +| Profile defaultcapture_admin | No inheritance, Cannot login +| Profile defaultenterprisedb | Superuser, Create role, Create DB, Replication, Bypass RLS+| Profile defaultpubuser | Replication +| Profile defaultrepuser | Replication +| Profile default
创建复制槽:
edb=# select pg_create_physical_replication_slot('primary');pg_create_physical_replication_slot-------------------------------------(primary,)(1 row)
创建示例表以发布:
edb=# create table t1(id int);CREATE TABLEedb=# drop table t1 ;DROP TABLEedb=# create table t1(id int primary key, name char(20));CREATE TABLEedb=# create table t2(id int primary key, name char(20));CREATE TABLEedb=# insert into t1 values (1, 'supriya');INSERT 0 1edb=# insert into t2 values (1, 'payal');INSERT 0 1edb=# table t1;id | name----+----------------------1 | supriya(1 row)edb=# table t2;id | name----+----------------------1 | payal(1 row)
授予 pubuser 选择表的权限:
printf("hello world!");
创建发布:
edb=# create publication testpub for all tables;CREATE PUBLICATION
检查复制槽和其他详细信息:
edb=# select * from pg_publication;oid | pubname | pubowner | puballtables | pubinsert | pubupdate | pubdelete | pubtruncate | pubviaroot-------+---------+----------+--------------+-----------+-----------+-----------+-------------+------------16399 | testpub | 10 | t | t | t | t | t | f(1 row)edb=# select * from pg_publicationpg_publication pg_publication_namespace pg_publication_rel pg_publication_tablesedb=# select * from pg_publication_tables ;pubname | schemaname | tablename | attnames | rowfilter---------+------------+-----------+-----------+-----------testpub | public | t1 | {id,name} |testpub | public | t2 | {id,name} |(2 rows)edb=# \dtList of relationsSchema | Name | Type | Owner--------+------+-------+--------------public | t1 | table | enterprisedbpublic | t2 | table | enterprisedb(2 rows)edb=#edb=# select * from pg_replication_slots ;slot_name | plugin | slot_type | datoid | database | temporary | active | active_pid | xmin | catalog_xmin | restart_lsn | confirmed_flush_lsn | wal_status | safe_wal_size | two_phase| conflicting-----------+--------+-----------+--------+----------+-----------+--------+------------+------+--------------+-------------+---------------------+------------+---------------+-----------+-------------primary | | physical | | | f | f | | | | | | | | f|(1 row)edb=# \q
1.2 在备用服务器上(数据目录 standby_data1)
通过 pg_basebackup 设置流复制:
$ /usr/edb/as16/bin/pg_basebackup -h localhost -U enterprisedb -p 5444 -D var/lib/edb/as16/standby_data1 -X stream -RP59051/59051 kB (100%), 1/1 tablespace
将端口更改为 5445 并启动服务器:
$ usr/edb/as16/bin/pg_ctl -D var/lib/edb/as16/standby_data1 startLOG: redirecting log output to logging collector processHINT: Future log output will appear in directory "log".doneserver started
检查是否处于恢复模式:
$ usr/edb/as16/bin/psql -d edb -p 5445psql (16.3.0)Type "help" for help.edb=# select pg_is_in_recovery();pg_is_in_recovery-------------------t(1 row)edb=# \q
1.3 在订阅服务器上(数据目录 logical_data)
初始化一个空的数据目录:
$ /usr/edb/as16/bin/initdb -D var/lib/edb/as16/logical_data
将端口更改为 5446 并启动服务器:
$ usr/edb/as16/bin/pg_ctl -D /var/lib/edb/as16/logical_data startLOG: redirecting log output to logging collector processHINT: Future log output will appear in directory "log".doneserver started
现在,我们在此服务器上运行了 3 个 Postgres 实例。Standby 正在从 Primary 进行复制,而 Subscriber 实例仍为空:
-bash-4.2$ ps -ef | grep postroot 1504 1 0 Jun09 ? 00:00:00 /usr/libexec/postfix/master -wpostfix 1520 1504 0 Jun09 ? 00:00:00 qmgr -l -t unix -uenterpr+ 11361 1 0 01:22 ? 00:00:00 /usr/edb/as16/bin/edb-postgres -D /var/lib/edb/as16/dataenterpr+ 11362 11361 0 01:22 ? 00:00:00 postgres: loggerenterpr+ 11363 11361 0 01:22 ? 00:00:00 postgres: checkpointerenterpr+ 11364 11361 0 01:22 ? 00:00:00 postgres: background writerenterpr+ 11366 11361 0 01:22 ? 00:00:00 postgres: walwriterenterpr+ 11367 11361 0 01:22 ? 00:00:00 postgres: autovacuum launcherenterpr+ 11368 11361 0 01:22 ? 00:00:00 postgres: dbms_aq launcherenterpr+ 11369 11361 0 01:22 ? 00:00:00 postgres: logical replication launcherenterpr+ 11467 1 0 01:24 ? 00:00:00 /usr/edb/as16/bin/edb-postgres -D /var/lib/edb/as16/standby_data1enterpr+ 11468 11467 0 01:24 ? 00:00:00 postgres: loggerenterpr+ 11469 11467 0 01:24 ? 00:00:00 postgres: checkpointerenterpr+ 11470 11467 0 01:24 ? 00:00:00 postgres: background writerenterpr+ 11471 11467 0 01:24 ? 00:00:00 postgres: startup recovering 000000010000000000000007enterpr+ 11472 11467 0 01:24 ? 00:00:01 postgres: walreceiver streaming 0/7000148enterpr+ 11473 11361 0 01:24 ? 00:00:00 postgres: walsender enterprisedb 192.168.84.9(33466) streaming 0/7000148postfix 12389 1504 0 02:15 ? 00:00:00 pickup -l -t unix -uenterpr+ 13749 1 0 03:43 ? 00:00:00 /usr/edb/as16/bin/edb-postgres -D /var/lib/edb/as16/logical_dataenterpr+ 13750 13749 0 03:43 ? 00:00:00 postgres: loggerenterpr+ 13751 13749 0 03:43 ? 00:00:00 postgres: checkpointerenterpr+ 13752 13749 0 03:43 ? 00:00:00 postgres: background writerenterpr+ 13754 13749 0 03:43 ? 00:00:00 postgres: walwriterenterpr+ 13755 13749 0 03:43 ? 00:00:00 postgres: autovacuum launcherenterpr+ 13756 13749 0 03:43 ? 00:00:00 postgres: dbms_aq launcherenterpr+ 13757 13749 0 03:43 ? 00:00:00 postgres: logical replication launcherenterpr+ 13763 11582 0 03:44 pts/0 00:00:00 grep --color=auto post-bash-4.2$
将主数据库的全局转储并还原到这里。确保在执行此命令之前调整 pg_hba.conf 文件:
$ /usr/edb/as16/bin/pg_dumpall -h localhost -p 5444 -U enterprisedb -g | /usr/edb/as16/bin/psql -d edb -h localhost -p 5446 -U enterprisedbSETSETSETALTER PROFILEERROR: role "enterprisedb" already existsALTER ROLECREATE ROLEALTER ROLECREATE ROLEALTER ROLE
使用备用服务器作为源创建订阅:
$ /usr/edb/as16/bin/psql -d edb -p 5446psql (16.3.0)Type "help" for help.edb=#edb=# create subscription testsub connection 'dbname=edb host=localhost port=5445 user=pubuser password=edb' publication testpub;NOTICE: created replication slot "testsub" on publisherCREATE SUBSCRIPTIONedb=#edb=# select * from pg_subscription;-[ RECORD 1 ]-------+-----------------------------------------------------------------oid | 16399subdbid | 15239subskiplsn | 0/0subname | testsubsubowner | 10subenabled | tsubbinary | fsubstream | fsubtwophasestate | dsubdisableonerr | fsubpasswordrequired | tsubrunasowner | fsubconninfo | dbname=edb host=192.168.84.9 port=5445 user=pubuser password=edbsubslotname | testsubsubsynccommit | offsubpublications | {testpub}suborigin | any
如果此过程尚未立即完成,可能是因为备用服务器仍在等待从主服务器同步数据。在这种情况下,可以在主服务器上调用 pg_log_standby_snapshot() 函数,以刷新备用服务器上的复制状态,从而使其他复制命令能够在备用服务器上执行。
在主服务器上:
$ /usr/edb/as16/bin/psql -d 5444 -d edbpsql (16.3.0)Type "help" for help.edb=#edb=# select pg_log_standby_snapshot();pg_log_standby_snapshot-------------------------0/70022B8(1 row)edb=#
二、 这种方法的优势
备用服务器上的几项强大功能,包括:
创建逻辑复制槽的能力
发起逻辑解码的能力
在备用服务器上订阅更改的能力
在故障转移后仍能保持逻辑复制槽的能力
三、 更新现有备用服务器以支持逻辑复制的能力
将备用服务器用作逻辑复制订阅者的源是一个无缝的过程,只需要进行一些调整:
启用 hot_standby_feedback = on;
使用物理复制槽从上游复制数据到备用服务器;
在主服务器上调用 pg_log_standby_snapshot(),确保订阅者在创建到备用服务器的订阅时不会停滞。
关于公司
感谢您关注新智锦绣科技(北京)有限公司!作为 Elastic 的 Elite 合作伙伴及 EnterpriseDB 在国内的唯一代理和服务合作伙伴,我们始终致力于技术创新和优质服务,帮助企业客户实现数据平台的高效构建与智能化管理。无论您是关注 Elastic 生态系统,还是需要 EnterpriseDB 的支持,我们都将为您提供专业的技术支持和量身定制的解决方案。
欢迎关注我们,获取更多技术资讯和数字化转型方案,共创美好未来!
![]() | ![]() |
Elastic 微信群 | EDB 微信群 |

发现“分享”和“赞”了吗,戳我看看吧






