一、发布订阅介绍
发布和订阅使用了pg的逻辑复制的功能,通过发布端创建publication与表绑定,订阅端创建subscription同时会在发布端创建逻辑复制槽实现逻辑复制功能
逻辑复制基于 发布(Publication) 与 订阅(Subscription)模型:
一个 发布者(Publisher) 上可以有多个发布,一个 订阅者(Subscriber) 上可以有多个 订阅 。
一个发布可被多个订阅者订阅,一个订阅只能订阅一个发布者,但可订阅同发布者上的多个不同发布。
逻辑复制的典型用途是:
迁移,跨PostgreSQL大版本,跨操作系统平台进行复制。
CDC,收集数据库(或数据库的一个子集)中的增量变更,在订阅者上为增量变更触发触发器执行定制逻辑。
分拆,将多个数据库集成为一个,或者将一个数据库拆分为多个,进行精细的分拆集成与访问控制。
复制标识:
一个被纳入发布中的表,必须带有复制标识(Replica Identity),只有这样才可以在订阅者一侧定位到需要更新的行,完成UPDATE与DELETE操作的复制。
默认情况下,主键 (Primary Key)是表的复制标识,非空列上的唯一索引 (UNIQUE NOT NULL)也可以用作复制标识。
如果没有任何复制标识,可以显式将复制标识设置为FULL,也就是把整个行当作复制标识
使用FULL模式的复制标识效率很低(因为每一行修改都需要在订阅者上执行全表扫描,很容易把订阅者拖垮),所以这种配置只能是保底方案。
使用FULL模式的复制标识还有一个限制,订阅端的表上的复制身份所包含的列,要么与发布者一致,要么比发布者更少
复制标识的影响:
- INSERT操作总是可以无视复制标识直接进行(因为插入一条新记录,在订阅者上并不需要定位任何现有记录;而删除和更新则需要通过复制标识 定位到需要操作的记录)。
- 如果一个没有 复制标识 的表被加入到带有UPDATE和DELETE的发布中,后续的UPDATE和DELETE会导致发布者上报错
显式配置复制标识:
alter table test3 REPLICA IDENTITY full;
create unique index idx_test4 on test4(id);
alter table test4 alter column id set not null;
alter table test4 REPLICA IDENTITY using index idx_test4;
select relname,relreplident from pg_class where relname in('test3','test4');
二、发布和订阅创建
发布端配置:
wal_level=logical
max_replication_slots大于订阅端的数量
max_wal_senders大于max_replication_slots
订阅端配置:
max_logical_replication_workers 逻辑复制进程数,应大于订阅节点的数量,并且给表同步预留一些进程数量
发布端操作:
1、创建复制用户并赋予复制权限
create user repuser password 'repuser' replication;
2、在postgres库中创建表
create table test1(id int primary key,name varchar(10) );
insert into test1 values(1,'a');
3、赋予复制用户select表权限
grant select on table t1 to repuser;
4、创建表test1的发布
create publication pub1 for table test1;
订阅端操作:
1、建发布端同名表
create table test1(id int primary key,name varchar(10) );
2、创建订阅
CREATE SUBSCRIPTION sub1 CONNECTION 'host=192.168.40.112 dbname=postgres port=5432 user=repuser password=repuser' PUBLICATION pub1;
3、查看表test1的数据是否被同步
在发布端执行test1表的insert、delete、update、truncate操作,看订阅端是否能同步
三、新加表同步
发布端:
1、新建表
create table test3 (id int,name varchar(10));
2、设置复制标识
alter table test3 REPLICA IDENTITY full;
3、将表加入发布
ALTER PUBLICATION pub1 ADD TABLE test3;
订阅端执行刷新:
ALTER SUBSCRIPTION sub1 REFRESH PUBLICATION ;
在发布端执行test3表的insert、delete、update、truncate操作,看订阅端是否能同步
四、发布订阅的相关视图(要在对应的库下查看)
发布端:
select * from pg_replication_slots; --查看所有复制槽
select * from pg_stat_replication; --查看复制槽的同步状态
select * from pg_publication; --查看所有发布
select * from pg_publication_tables; --查看所有发布对应的表
select usename,a.pubname,c.*,pubinsert,pubupdate,pubdelete,pubtruncate from pg_publication a,pg_user b,pg_publication_tables c where a.pubowner=b.usesysid and c.pubname=a.pubname;
订阅端:
select * from pg_subscription; --查看所有订阅
select srrelid::regclass from pg_subscription_rel; --查看订阅的所有表
select usename,datname,subname,srrelid::regclass,srsublsn,subconninfo from pg_subscription a,pg_user b,pg_subscription_rel c ,pg_database d where a.oid=c.srsubid and a.subowner=b.usesysid and a.subdbid=d.oid;