目录
环境
文档用途
详细信息
环境
系统平台: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操作的结果。
图示:
四、逻辑复制的主要组成
1)publication - 发布
可以在任何物理复制主机上定义发布; 定义发布的节点称为发布者;
发布是从一个表或一组表中生成的一组更改,也可能被描述为更改集或复制集;
每个发布只存在于一个数据库中。
发布与模式不同,不影响表格的访问方式;如果需要,每张表可以添加到多个发布;
发布目前可能只包含表;对象必须显式添加, 除非为ALL TABLES创建了一个发布。
发布可以选择将它们所产生的改变限制在INSERT, UPDATE和DELETE的任意组合上, 类似于触发器
默认情况下,复制所有操作类型
publication - 发布语法
postgres=# \h create publication postgres=# \h alter publication |
publication - 发布语法示例
CREATE PUBLICATION mypublication FOR TABLE users, departments; |
2)subscription - 订阅
subscription - 订阅语法
postgres=# \h create subscription postgres=# \h alter subscription postgres=# \h drop subscription |
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 parttest1 PARTITION OF
|
六、逻辑复制示例
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); select * from pg_publication; #查看创建的发布,信息不详细,譬如没有关联发布的表
--如果 表设置为REPLICA IDENTITY default,表不允许删除操作,具体如下:
postgres=# ALTER TABLE postgres.test_lr2 REPLICA IDENTITY FULL;
--查看订阅端同步情况,同步成功! |
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); create subscription sub1 connection 'host=192.168.137.55 port=1922 dbname=postgres user=repuser password=repuser' publication pub1;-- --create table postgres.test_lr2(id int4 ,name text); --select * from postgres.test_lr2 ; |
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