PostgreSQL逻辑订阅

逻辑订阅是PostgreSQL10.0开始支持的新功能,PostgreSQL的物理流复制功能十分强大,在容灾、读写分离、HA等场景中都有广泛的使用,那么为什么还需要逻辑订阅呢?
我们先来看看物理流复制和逻辑订阅有哪些区别,主要有以下几点不同:
物理复制目前只能做到整个集群的复制。逻辑订阅可以做到针对某个对象
物理复制的备库只读,不能写入。逻辑订阅读写都可以
物理复制不需要等待事务提交,逻辑订阅,目前需要等待事务提交后,发布端才会使用wal_sender进程将decode后的数据发送给订阅端,订阅端流式接收与流式apply,因此逻辑订阅对主库性能影响较大

逻辑订阅实践:
在使用逻辑订阅之前我们需要对数据库进行一些配置:
发布端:
配置pg_hba.conf,允许订阅端通过流复制连接发布端
wal_level必须设置为logical
发布端的角色必须具备replication权限,或者超级用户权限
订阅端:
创建subscription的用户,必须是超级用户

这些基本的一些准备做好之后,就可以开始配置逻辑订阅了:
1、配置发布端

postgres=# create table t1(id int primary key, info text, crt_time timestamp);
CREATE TABLE
postgres=# create publication testpub1 for table t1;
CREATE PUBLICATION

–查看当前数据库有哪些发布

postgres=# select * from pg_publication;  
 pubname  | pubowner | puballtables | pubinsert | pubupdate | pubdelete 
----------+----------+--------------+-----------+-----------+-----------
 testpub1 |       10 | f            | t         | t         | t
(1 row)

2、配置订阅端

postgres=# create table t1(id int primary key, info text, crt_time timestamp);  
CREATE TABLE
postgres=# create subscription testsub1 connection 'hostaddr=xxx.xxx.xxx.xxx port=1921 user=postgres dbname=postgres' publication testpub1 with (enabled, create_slot, slot_name='sub1_from_pub1');  
NOTICE:  created replication slot "sub1_from_pub1" on publisher
CREATE SUBSCRIPTION

–查看有哪些订阅

postgres=# select * from pg_subscription ;  
 subdbid | subname  | subowner | subenabled |                          subconninfo                           |  subslotname   | subsynccommit | subpublications 
---------+----------+----------+------------+----------------------------------------------------------------+----------------+---------------+-----------------
   16401 | testsub1 |       10 | t          | hostaddr=192.168.7.177 port=1921 user=postgres dbname=postgres | sub1_from_pub1 | off           | {testpub1}
(1 row)

postgres=# select * from pg_stat_subscription ;  
 subid | subname  | pid  | relid | received_lsn |      last_msg_send_time       |     last_msg_receipt_time     | latest_end_lsn |        latest_end_time        
-------+----------+------+-------+--------------+-------------------------------+-------------------------------+----------------+-------------------------------
 44943 | testsub1 | 7877 |       | 1/76119308   | 2019-09-10 13:20:07.497634+08 | 2019-09-11 01:23:39.104443+08 | 1/76119308     | 2019-09-10 13:20:07.497634+08
(1 row)

数据库插入测试:
–发布端:

postgres=# insert into t1 select t,md5(random()::text),clock_timestamp() from generate_series(1,1000) t;
INSERT 0 1000

然后我们去订阅端查看:

postgres=# select count(*) from t1;
 count 
-------
  100
(1 row)
postgres=# select * from t1 limit 10;
 id |               info               |          crt_time          
----+----------------------------------+----------------------------
  1 | 31422ff05d990455a4632bf97cbcda45 | 2019-09-10 13:21:57.780586
  2 | 4a3f42ed6421f89cdf8c09e221431520 | 2019-09-10 13:21:57.780713
  3 | 88423917787f7c99340668c324fc35d2 | 2019-09-10 13:21:57.78072
  4 | 11dd182301956e9458460fc3f33cc5d6 | 2019-09-10 13:21:57.780724
  5 | bd0a78455bc400b39a697148a564e9eb | 2019-09-10 13:21:57.780727
  6 | 6b3b36fd0fe55d49932b990809913744 | 2019-09-10 13:21:57.78073
  7 | 3e13b1856a5f5623acfe607de775f0c1 | 2019-09-10 13:21:57.780733
  8 | f7b51908bf88974a7532ce0ec760d585 | 2019-09-10 13:21:57.780736
  9 | f9002e38c2fb8a3ed6c0453d518815aa | 2019-09-10 13:21:57.780739
 10 | ea68f6d87051fb8fef4586c0a2c04f5c | 2019-09-10 13:21:57.780741
(10 rows)

这里需要注意,目前逻辑订阅不支持DDL语句的同步,例如:
–发布端:

postgres=# truncate t1;
TRUNCATE TABLE

再去订阅端查看,数据库还是没有变化

postgres=# select count(*) from t1;
 count 
-------
  1000
(1 row)

因为逻辑订阅实际上和MySQL binglog复制类似,但是DDL是不写表的,那么DDL如何复制呢?
比较简单的一种方法就是:将DDL记录下来,写入表中,在订阅端对这个表创建触发器,在触发器内执行DDL即可。需要被订阅的对象,建上对应的触发器即可。
总的来说,PostgreSQL的逻辑订阅目前还是有限局限性,并且和物理流复制相比性能差距较明显,但是对于在某些物理流复制无法实现的场景,使用逻辑订阅还是能够起到很大的作用!

参考链接:https://www.postgresql.org/docs/12/logical-replication.html

发布了70 篇原创文章 · 获赞 5 · 访问量 3157

猜你喜欢

转载自blog.csdn.net/weixin_39540651/article/details/100707511