暂无图片
暂无图片
1
暂无图片
暂无图片
暂无图片

搭建一个多主复制数据回环场景

原创 小满未满、 2025-06-16
210

一、前言

最近也是看着看着,看到了逻辑复制这块,事实上我很少接触过这块,所以就当练练手了。

参考:https://boringsql.com/posts/logication-replication-introduction/

这里我打算在一台虚拟机上部署两个PostgreSQL实例,搭建一个双向复制的数据回环场景,

当然想要看到数据回环的效果的话,当前的PostgreSQL版本必须低于16,这里我的版本是15。


二、搭建

开启两个会话,会话一初始化数据库目录15,会话二初始化数据库目录2-15

然后会话一 修改数据库目录中的配置文件,在文件中添加下面信息

wal_level = logical
max_replication_slots = 10
max_wal_senders = 10
listen_addresses = '*'
logging_collector = on 
log_min_messages = info

会话二 修改配置文件 添加下面信息,和会话一唯一区别在于端口不同

wal_level = logical
max_replication_slots = 10
max_wal_senders = 10
listen_addresses = '*'
logging_collector = on 
log_min_messages = info
port=1921

然后分别启动数据库,为了简单方便,等会在搭建的时候,我直接使用我的超级用户zxm,

更推荐的自然是创建专属的复制用户来干这些事情。

在搭建双向复制的之前,其实就是一个简单的逻辑复制搭建。

这里我在会话一创建logical_demo_publisher数据库,在会话二创建my_subscriber_db数据库。

两个数据库存在名为products的表,且表结构一致。

定义语句如下:

CREATE TABLE products (
    name TEXT NOT NULL,
    category TEXT,
    price DECIMAL(10, 2) NOT NULL,
    stock_quantity INT DEFAULT 0,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    description TEXT,
    is_active BOOLEAN DEFAULT TRUE
);

之后在会话一,往表中插入10行数据

INSERT INTO products (
    name,
    category,
    price,
    stock_quantity,
    description,
    is_active
)
SELECT
    'Product Batch ' || s.id AS name,
    CASE (s.id % 5)
        WHEN 0 THEN 'Electronics'
        WHEN 1 THEN 'Books'
        WHEN 2 THEN 'Home Goods'
        WHEN 3 THEN 'Apparel'
        ELSE 'Miscellaneous'
    END AS category,
    ROUND((RANDOM() * 500 + 10)::numeric, 2) AS price,
    FLOOR(RANDOM() * 200)::int AS stock_quantity,
    'Auto-generated description for product ID ' || s.id || '. Lorem ipsum dolor sit amet, consectetur adipiscing elit.' AS description,
    (s.id % 10 <> 0) AS is_active
FROM generate_series(1, 10) AS s(id);

在数据准备完毕之后,让我们来搭建逻辑复制,其实也非常简单,就是一个发布,一个订阅

在会话一中执行下面语句,进行发布

CREATE PUBLICATION my_publication FOR TABLE products;

运行如下图所示:

在会话二中,执行以下语句进行订阅(记得修改成对应的用户)

CREATE SUBSCRIPTION my_subscription
    CONNECTION 'host=127.0.0.1 port=5432 user=zxm dbname=logical_demo_publisher'
    PUBLICATION my_publication;

执行完成之后,事实上对于表products的逻辑复制便以及成功搭建好了。

让我们在会话二查看一下表products中的相关数据总数是否和会话一中的一致。

可以看到的是数据条数是一致的。实际的逻辑就是logical_demo_publisher --> my_subscriber_db

接下来我们来完成双向复制,也就是my_subscriber_db --> logical_demo_publisher ,从而触发数据回环

会话二执行如下语句,进行发布的动作

CREATE PUBLICATION my_publication2 FOR TABLE products;

会话一执行如下语句,(记得修改用户),执行订阅动作

 CREATE SUBSCRIPTION my_subscription2
    CONNECTION 'host=127.0.0.1 port=1921 user=zxm dbname=my_subscriber_db'
    PUBLICATION my_publication2;

然后分别在各自的会话,查询表中数据,如下所示:

然后就可以看到,虽然两个会话什么都没做,一个INSERT都没看到但是表中的数据在疯涨,这便出现了数据回环。

logical_demo_publisher <--> my_subscriber_db


三、如何解决这个问题

其实升级到16版本就没有这个问题的。或者是修改表结构新增一些逻辑来区分数据是哪里来的,通过触发器或者一些手段来解决。

但是可能有的朋友无法升级数据库的大版本,毕竟16版本在国内还是算的上是非常新的版本,同时也不想修改逻辑、表结构啥啥啥的。

下一篇我将介绍一个插件,来解决这个问题,敬请期待~


四、声明

若文中存在错误或不当之处,敬请指出,以便我进行修正和完善。希望这篇文章能够帮助到各位。

文章转载请联系,谢谢合作~

更多详细内容请阅读PostgreSQL官方文档~

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

评论