暂无图片
暂无图片
5
暂无图片
暂无图片
暂无图片

PostgreSQL 17.2 逻辑复制搭建

原创 飞天 2024-12-14
434

逻辑复制介绍

原理:

逻辑复制是解析WAL日志,将Publication(发布端)中表的WAL日志解析成一定格式并发送给Subscription(订阅端),Subscription接收到解析后的WAL日志后进行重放应用,从而实现表数据的同步。

优点:

  • 流复制只能做到整个cluster的复制,而逻辑复制则更加灵活,可以做到库级别、表级别的同步
  • 流复制的standby备库是只读的,不能写⼊,⽽逻辑复制备库读写都可以。
  • 逻辑复制⽀持不同os架构,不同数据库版本之间的数据复制

缺点:

  • 逻辑复制的配置和流复制相比相对复杂。
  • 相对于流复制,逻辑复制可能存在一定的复制延迟。逻辑复制需要等待事务提交后,发布端才会使用wal_sender进程将decode后的数据发送给订阅端。
  • 逻辑复制不支持DDL复制(ALTER TABLE/CREATE TABLE)
  • 逻辑复制只支持表复制,不支持其他对象的复制

适用场景:

  • 指定库或部分表的复制需求
  • 将多个数据库实例的数据汇聚到同一个目标库
  • 将一个库的数据分发到多个不同的库
  • 不同的版本之间的复制
  • 不同库名之间的表同步
  • 无停机升级数据库
  • 跨版本升级数据库

注意:
逻辑复制会在发布端创建逻辑复制槽,如果订阅端数据库异常,一直没有消费发布端的wal日志,会导致发布端wal日志的堆积进而存在磁盘撑爆的风险,需要特别注意。

逻辑复制搭建

搭建流程

image.png

环境说明

主机名 ip地址 OS版本 内存、CPU 数据库端口 节点角色
node1 192.*.*.60 Centos7.9 4G 、 1个双核 5555 发布端
node2 192.*.*.62 Centos7.9 4G 、 1个双核 5555 订阅端

发布端数据库参数要求

max_replication_slots = 10 #复制槽的最大数量 hot_standby = on #允许在应用WAL日志的同时,提供只读服务 wal_level = logical #逻辑复制中必须是 logical #hot_standby_feedback = on #数据接收端需要进行回馈 max_wal_senders = 10 #wal sender的最大数量 #pg17中需要修改下面两个参数: postgres=# alter system set wal_level=logical; ALTER SYSTEM postgres=# alter system set max_replication_slots=10; ALTER SYSTEM postgres=# alter system set max_wal_senders=12; --应该将此参数设置的比 max_replication_slots 参数要大 #修改参数后需要重启数据库才能生效: pg_ctl restart

订阅端数据库参数要求

max_replication_slots = 10 #复制槽的最大数量 max_logical_replication_workers #逻辑复制worker进程的最大数量 #pg17中需要修改下面两个参数: postgres=# alter system set max_replication_slots=10; ALTER SYSTEM postgres=# alter system set max_logical_replication_workers=10; ALTER SYSTEM postgres=# #修改参数后需要重启数据库才能生效: pg_ctl restart

发布端创建逻辑复制用户

create user replusr with password '******'; alter user replusr replication; #创建测试表 create table tab1(id int primary key,name varchar(100)); insert into tab1 values(1,'a'); insert into tab1 values(2,'b'); insert into tab1 values(3,'c'); insert into tab1 values(4,'d'); insert into tab1 values(5,'e');

发布端创建发布

创建发布语法如下: postgres=# \h create publication Command: CREATE PUBLICATION Description: define a new publication Syntax: CREATE PUBLICATION name [ FOR ALL TABLES | FOR publication_object [, ... ] ] [ WITH ( publication_parameter [= value] [, ... ] ) ] where publication_object is one of: TABLE [ ONLY ] table_name [ * ] [ ( column_name [, ... ] ) ] [ WHERE ( expression ) ] [, ... ] TABLES IN SCHEMA { schema_name | CURRENT_SCHEMA } [, ... ] URL: https://www.postgresql.org/docs/17/sql-createpublication.html postgres=#

创建发布:

create publication pub_tab1 for table tab1; # 查询发布信息 select * from pg_publication;

订阅端创建空表

create table tab1(id int primary key,name varchar(100));

订阅端创建订阅

postgres=# \h create subscription Command: CREATE SUBSCRIPTION Description: define a new subscription Syntax: CREATE SUBSCRIPTION subscription_name CONNECTION 'conninfo' PUBLICATION publication_name [, ...] [ WITH ( subscription_parameter [= value] [, ... ] ) ] URL: https://www.postgresql.org/docs/17/sql-createsubscription.html postgres=#

创建订阅示例:

create subscription sub_tab1 connection 'host=192.*.*.60 port=5555 dbname=postgres user=replusr password=******' publication pub_tab1; 说明:创建订阅的同时会在发布端创建逻辑复制槽,保证没有被订阅端消费的wal日志不能被删除。 #查询订阅信息 select * from pg_subscription;

image.png

订阅端查询数据同步情况

postgres=# select * from tab1; id | name ----+------ (0 rows) 数据没有同步过来。

数据没有同步的分析过程:

检查订阅端的数据库日志

2024-12-14 23:16:41.711 CST [19256] LOG:  logical replication table synchronization worker for subscription "sub_tab1", table "tab1" has started
2024-12-14 23:16:41.762 CST [19256] ERROR:  could not start initial contents copy for table "public.tab1": ERROR:  permission denied for table tab1
2024-12-14 23:16:41.764 CST [18578] LOG:  background worker "logical replication tablesync worker" (PID 19256) exited with exit code 1

从日志可以发现,复制用户replusr对表所属的schema(public)及表(tab1)没有读写权限。
在发布端进行表授权

postgres=# grant usage on schema public to replusr; GRANT postgres=# grant select on tab1 to replusr ; GRANT postgres=# alter default privileges in schema public grant select on tables to replusr ; ALTER DEFAULT PRIVILEGES

订阅端再次检查数据同步情况

postgres=# select * from tab1; id | name ----+------ 1 | a 2 | b 3 | c 4 | d 5 | e (5 rows) postgres=#

附录

PostgreSQL 17.2安装部署

请参考文章 PostgreSQL 17.2 数据库编译安装

总结

PostgreSQL逻辑复制搭建过程还是挺容易的,但是实际生产过程中可能会碰到各种问题,对数据同步有高要求的系统需要慎用。

关于作者:
专注于Oracle、MySQL、PG、OpenGauss和国产数据库的研究,热爱生活,热衷于分享数据库技术。
微信公众号:飞天online
墨天轮:https://www.modb.pro/u/15197
如有任何疑问,欢迎大家留言,共同进步~~~

最后修改时间:2024-12-15 20:28:38
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论