PostgreSQL V10逻辑复制最佳实践

目录

环境

文档用途

详细信息

环境

系统平台:Linux x86-64 Red Hat Enterprise Linux 7

版本:10.1

文档用途

PostgreSQL V10逻辑复制原理以及作为逻辑复制使用指导

详细信息

一、什么是逻辑复制(pglogical)
逻辑复制是PostgreSQL V10重量级新特性,支持内置的逻辑复制。在10版本之前,虽然没有内置的逻辑复制,也可以通过其它方式实现,例如触发器、自定义脚本实现表级别同步,另外也可以通过外部工具 Londiste3 实现。从2014年发布的9.4版本开始,PostgreSQL就支持逻辑复制了,只是一直没有将其引入内核。你可以针对同一个数据库实例,同时使用逻辑复制和物理复制,因为他们都是基于REDO的。

二、逻辑复制应用场景
可基于表级别复制,是一种粒度可细的复制,主要用在以下场景:
1)满足业务上需求,实现某些指定表数据同步
2)报表系统,采集报表数据
3)PostgreSQL 跨版本数据同步
4)PostgreSQL 大版本升级
5)可从多个上游服务器,做数据的聚集和合并

三、逻辑复制原理
使用发布者/订阅者模型,使用订阅复制槽技术,可并行的传输WAL日志,通过在订阅端回放WAL日志中的逻辑条目,保持复制表的数据同步,
注意这里不是“SQL”复制,而是复制SQL操作的结果。

图示:

PostgreSQL V10逻辑复制最佳实践_第1张图片

 

四、逻辑复制的主要组成
1)publication - 发布
可以在任何物理复制主机上定义发布; 定义发布的节点称为发布者;
发布是从一个表或一组表中生成的一组更改,也可能被描述为更改集或复制集;
每个发布只存在于一个数据库中。
发布与模式不同,不影响表格的访问方式;如果需要,每张表可以添加到多个发布;
发布目前可能只包含表;对象必须显式添加, 除非为ALL TABLES创建了一个发布。
发布可以选择将它们所产生的改变限制在INSERT, UPDATE和DELETE的任意组合上, 类似于触发器
默认情况下,复制所有操作类型

publication - 发布语法

postgres=# \h create publication 
Command:     CREATE PUBLICATION
Description: define a new publication
Syntax:
CREATE PUBLICATION name
    [ FOR TABLE [ ONLY ] table_name [ * ] [, ...]
      | FOR ALL TABLES ]
    [ WITH ( publication_parameter [= value] [, ... ] ) ]

postgres=# \h alter publication 
Command:     ALTER PUBLICATION
Description: change the definition of a publication
Syntax:
ALTER PUBLICATION name ADD TABLE [ ONLY ] table_name [ * ] [, ...]
ALTER PUBLICATION name SET TABLE [ ONLY ] table_name [ * ] [, ...]
ALTER PUBLICATION name DROP TABLE [ ONLY ] table_name [ * ] [, ...]
ALTER PUBLICATION name SET ( publication_parameter [= value] [, ... ] )
ALTER PUBLICATION name OWNER TO { new_owner | CURRENT_USER | SESSION_USER }
ALTER PUBLICATION name RENAME TO new_name

publication - 发布语法示例

CREATE PUBLICATION mypublication FOR TABLE users, departments;

2)subscription - 订阅

subscription - 订阅语法

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] [, ... ] ) ]

postgres=# \h alter subscription 
Command:     ALTER SUBSCRIPTION
Description: change the definition of a subscription
Syntax:
ALTER SUBSCRIPTION name CONNECTION 'conninfo'
ALTER SUBSCRIPTION name SET PUBLICATION publication_name [, ...] [ WITH ( set_publication_option [= value] [, ... ] ) ]
ALTER SUBSCRIPTION name REFRESH PUBLICATION [ WITH ( refresh_option [= value] [, ... ] ) ]
ALTER SUBSCRIPTION name ENABLE
ALTER SUBSCRIPTION name DISABLE
ALTER SUBSCRIPTION name SET ( subscription_parameter [= value] [, ... ] )
ALTER SUBSCRIPTION name OWNER TO { new_owner | CURRENT_USER | SESSION_USER }
ALTER SUBSCRIPTION name RENAME TO new_name

postgres=# \h drop subscription 
Command:     DROP SUBSCRIPTION
Description: remove a subscription
Syntax:
DROP SUBSCRIPTION [ IF EXISTS ] name [ CASCADE | RESTRICT ]

subscription - 订阅语法示例

创建一个到远程服务器的订阅,复制发布mypublication和 insert_only中的表,并在提交时立即开始复制:

CREATE SUBSCRIPTION mysub
CONNECTION 'host=192.168.1.50 port=5432 user=foo dbname=foodb'
PUBLICATION mypublication, insert_only;

创建一个到远程服务器的订阅,复制insert_only发布中的表, 并且不开始复制直到稍后启用复制。

CREATE SUBSCRIPTION mysub
CONNECTION 'host=192.168.1.50 port=5432 user=foo dbname=foodb'
PUBLICATION insert_only WITH (enabled = false);

将订阅的发布更改为insert_only:

ALTER SUBSCRIPTION mysub SET PUBLICATION insert_only;

禁用(启用)订阅:

ALTER SUBSCRIPTION mysub DISABLE;
ALTER SUBSCRIPTION mysub ENABLE;


subscription - 订阅相关配置
这些设置控制逻辑复制订阅的行为。发布者的值无关紧要。
请注意,wal_receiver_timeout和 wal_retrieve_retry_interval配置参数还影响逻辑复制工作。

max_logical_replication_workers (int)
指定逻辑复制工作的最大数量。这包括应用工作和表同步工作。
逻辑复制工作进程是从max_worker_processes 定义的进程池中取出的。
默认值是4。

max_sync_workers_per_subscription (integer)
每个订阅的最大同步工作者数量。 此参数控制订阅初始化期间或添加新表时初始数据副本的并行数量。
目前,每个表只能有一个同步工作进程。
同步工作进程是从max_logical_replication_workers 定义的进程池中取出的。
默认值是2。

3)Replication Slots - 复制槽(发布端)

每个(活动)订阅都从远程(发布)端的复制槽接收更改。
通常,使用CREATE SUBSCRIPTION 创建订阅时会自动创建远程复制槽,使用DROP SUBSCRIPTION 删除订阅时会自动删除该槽。
复制槽提供了一种自动化的方法来确保主控机在所有的后备机收到 WAL段之前不会移除它们,主库随时知道从库应用 wal 的情况 , 哪怕从库掉线,主库依然保留 wal日志
这种机制的缺点是,如果从库掉线很久, 那么主库的wal日志 会一直保留以至于撑暴硬盘, 这时监控需要做到位。

Replication Slots - 复制槽(发布端)

#postgresql.conf关联配置

wal_level = logical
max_replication_slots = 10  #max_replication_slots 值最少需设置成 1,设置后重启数据库生效。

五、逻辑复制的限制

1)版本限制

pglogical是逻辑复制的技术组件,功能使用存在数据库版本限制:

数据源发布和订阅节点需要运行 PostgreSQL 9.4 +

复制源过滤和冲突检测需要 PostgreSQL 9.5 +

pglogical 支持跨 PostgreSQL 主要版本之间的复制
但在订阅服务器上不同版本之间进行复制时,可能会出现问题。

支持从旧版本复制到新版本因为 PostgreSQL 的向后兼容性保证的,但只有有限的向前兼容性比较安全

2)其它限制

不支持DDL复制(ALTER TABLE/CREATE TABLE)

不支持TEMPRORARY表和UNLOGGED表复制

不支持Sequences复制( serial/bigserial/identity)

不支持TRUNCATE操作复制
不支持大对象复制(Bytea)

不支持视图、物化视图、外部表复制


被复制的表上最好有主键约束;如果没有,必须执行:
ALTER TABLE reptest REPLICA IDENTITY FULL;(备注)

订阅端的复制表是可修改的,复制表一旦修改,发布者和订阅者会数据不一致,进而打破复制。

以下两种情况逻辑复制不支持:

publisher->public.foo replicates to subscriber→private.foo

publisher->public.foo replicates to subscriber->partitioned->public.foo

备注:REPLICA IDENTITY
这种形式更改被写入到预写式日志来标识被更新或删除行的信息。除非使用逻辑复制, 这个选项将不会产生效果。

DEFAULT(非系统表的默认值)记录主键列 (如果有)的旧值。

USING INDEX记录被所提到的索引所覆盖的列的 旧值,该索引必须是唯一索引、不是部分索引、不是可延迟索引并且只包括被标记成 NOT NULL的列。

FULL记录行中所有列的旧值。

NOTHING不记录有关旧行的任何信息(这是系统表的默认值)。在所 有情况下,除非至少有一个要被记录的列在新旧行版本之间发生变化,将不记录旧值。
分区表的逻辑复制,需要面向子表创建发布

CREATE TABLE parttest (id bigint, test text);

– PRIMARY KEYS don’t work on partitioned tables


CREATE TABLE parttest0 PARTITION OF
parttest FOR VALUES FROM (1) TO (100);

CREATE TABLE parttest1 PARTITION OF
parttest FOR VALUES FROM (101) TO (200);


CREATE PUBLICATION parttest FOR TABLE parttest0,parttest1

六、逻辑复制示例

1.规划发布、订阅节点(可以是一台主机的两个实例,或者不同主机的两个实例)

 

本示例是两台虚拟主机的两个实例

PG版本:Postgresql V10.3

发布端:192.168.137.55  port :1922

订阅端:192.168.137.66
2.发布节点配置文件

postgresql.conf:
wal_level = logical
listen_addresses = '*'
pg_hba.conf:
host repuser all 192.168.137.66/32 trust

3.发布节点创建复制用户

create user repuser replication login connection limit 10 encrypted password 'repuser'

备注:用于逻辑复制的用户必须是replication 角色 superuser 角色
4.发布节点为复制表创建发布

create schema postgres;

create table  postgres.test_lr1(id int4 primary key ,name text);

insert into postgres.test_lr1 values (1,'a');

表postgres.test_lr2关联测试发布端要发布的表不含主键的情况,以及如何修改发布,添加发布表。

--create table postgres.test_lr2(id int4,name text); 
--insert into postgres.test_lr2 values (1,'a');
--ALTER TABLE  postgres.test_lr2 REPLICA IDENTITY FULL;
--ALTER PUBLICATION pub1 ADD TABLE test_lr2; 

select * from pg_publication;         #查看创建的发布,信息不详细,譬如没有关联发布的表

 

--如果 表设置为REPLICA IDENTITY default,表不允许删除操作,具体如下:
ALTER TABLE  postgres.test_lr2 REPLICA IDENTITY default;
ALTER TABLE
postgres=# insert into postgres.test_lr2 values (3,'c');
INSERT 0 1
postgres=# delete from postgres.test_lr2 where id=3;
ERROR:  cannot delete from table "test_lr2" because it does not have a replica identity and publishes deletes
HINT:  To enable deleting from the table, set REPLICA IDENTITY using ALTER TABLE.

 

postgres=# ALTER TABLE  postgres.test_lr2 REPLICA IDENTITY FULL;
ALTER TABLE
postgres=# delete from postgres.test_lr2 where id='3';
DELETE 1

 

--查看订阅端同步情况,同步成功!

5.  发布节点为复制用户授权

grant connect on database postgres to repuser;

grant usage on schema postgres to repuser;

grant select on test_lr1 to repuser;

--grant select on test_lr2 to repuser;

6.  订阅节点创建接收表及订阅

create schema postgres;

create table postgres.test_lr1(id int4 ,name text);
alter table postgres.test_lr1 add primary key(id);  --没有主键,数据同步将会报错

create subscription sub1 connection 'host=192.168.137.55 port=1922 dbname=postgres user=repuser password=repuser' publication pub1;--
--drop subscription sub1
select * from pg_subscription;

--create table postgres.test_lr2(id int4 ,name text);

--select * from postgres.test_lr2 ;
ALTER SUBSCRIPTION sub1 REFRESH PUBLICATION ;

7.  配置完成,发布节点分别向表中插入、删除数据

insert into test_lr1 values (2,'b');

delete from test_lr1 where id=1;


8.  订阅节点查看逻辑复制效果

select * from postgres.test_lr1 ;

注意:订阅端被复制的表没有主键(发布端表上含有主键),数据同步会报错,参考如下:
2018-07-18 09:40:26.330 CST [49790] ERROR:  logical replication target relation "postgres.test_lr1" has neither REPLICA IDENTITY index nor PRIMARY KEY and published relation does not have REPLICA IDENTITY FULL

详细的解决办法请登录【瀚高技术支持平台】查看

https://support.highgo.com/#/index/docContent/85b52b41042b0b6d
 

你可能感兴趣的:(Highgo,DB)