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

PostgreSQL逻辑复制原理浅析



前言

昨天我们安装了PostgreSQL 13逻辑复制,今天我们来详细介绍一下它的原理。

逻辑复制的体系结构

逻辑复制体系结构如下图,来自于Noriyoshi ShinodaLogical Replication Internals

wal sender进程

逻辑解码插件pgoutput对WAL文件进行逻辑解码,然后wal sender进程将解码后的消息发送到订阅端。在发布实例进程如下所示:

如果有多个订阅进程,则会对应启动多个wal sender进程。例如我在从库再发起一个订阅。

--从库执行
hr=> CREATE TABLE jobs2 (
hr(>         job_id varchar(10) NOT NULL,
hr(>         job_title varchar(35) NOT NULL,
hr(>         min_salary integer,
hr(>         max_salary integer
hr(> ) ;
CREATE TABLE

hr=# create subscription testsub2 connection 'host=192.168.56.119 port=5432 dbname=hr user=replication' publication testpub;
CREATE SUBSCRIPTION

此时查看主库可以发现wal sender进程为2个。

logical replication launcher进程

logical replication launcher进程,在发布实例和订阅实例都存在。主要的作用就是启动逻辑复制工作进程。

logical replication worker for subscription进程

只在订阅实例上存在,每一个订阅都会启动一个对应的进程,它和wal sender进程进行连接,接收wal sender传输过来的信息并更新对应的表。

创建PUBLICATION之后

当我们创建PUBLICATION
之后,默认会将信息存储在pg_publication
视图中。其中包含发布的名字,哪些类型的DML语句能被复制。puballtables
字段如果为true,则代表包括数据库中的所有表,包括将来将要创建的任何表。

hr=> select * from pg_publication;
-[ RECORD 1 ]+--------
oid          | 57510
pubname      | testpub
pubowner     | 57496
puballtables | f
pubinsert    | t
pubupdate    | t
pubdelete    | t
pubtruncate  | t
pubviaroot   | f

另外一个视图pg_publication_rel
存储着表的oid和PUBLICATION的oid。如果指定了FOR ALL TABLES
选项,则此表中不存储任何内容。

hr=> select * from  pg_publication_rel;
-[ RECORD 1 ]--
oid     | 57511
prpubid | 57510
prrelid | 57504

视图pg_publication_tables
存储了表的名字、schema和发布的名称。

-[ RECORD 1 ]-------
pubname    | testpub
schemaname | public
tablename  | jobs

创建SUBSCRIPTION之后

当创建了SUBSCRIPTION
之后,默认信息存储在pg_subscription
视图中。该视图存储了连接到发布端的信息,复制插槽的名字,已经连接上的发布的名字。使用同步复制还是异步复制,当前可以看到都是异步复制。

hr=# select * from pg_subscription;
-[ RECORD 1 ]---+---------------------------------------------------------
oid             | 16392
subdbid         | 16385
subname         | testsub
subowner        | 10
subenabled      | t
subconninfo     | host=192.168.56.119 port=5432 dbname=hr user=replication
subslotname     | testsub
subsynccommit   | off
subpublications | {testpub}
-[ RECORD 2 ]---+---------------------------------------------------------
oid             | 32771
subdbid         | 16385
subname         | testsub2
subowner        | 10
subenabled      | t
subconninfo     | host=192.168.56.119 port=5432 dbname=hr user=replication
subslotname     | testsub2
subsynccommit   | off
subpublications | {testpub}

订阅连接到发布实例之后,会做以下几件事:

  • 检查连接用户,是否具备复制权限。

  • 在订阅侧创建逻辑复制插槽,插槽的名字默认和订阅名字保持一致。

  • 它不会检查发布是否存在。

  • pg_subscription_rel
    表中注册复制目标表。

hr=# select * from pg_subscription_rel;  
-[ RECORD 1 ]---------
srsubid    | 16392
srrelid    | 16386
srsubstate | r
srsublsn   | 0/1D8DDB0
-[ RECORD 2 ]---------
srsubid    | 32771
srrelid    | 16386
srsubstate | r
srsublsn   | 0/1DC2D30

  • 同步初始化数据。

  • 订阅实例如果存在数据,它不会删除。

  • 下图时初始化同步数据的过程。

可以看到第3和第4步,它会创建一个临时的插槽,并拷贝全部的数据过去。而增量的数据则继续通过之前的插槽传输。

后记

未完,待续。。。

参考链接

1.https://www.slideshare.net/noriyoshishinoda/pgconfasia-2017-logical-replication-internals-english?from_action=save


励志成为PostgreSQL大神

长按关注吧




文章转载自励志成为PostgreSQL大神,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论