目录
应用场景简介
分类
搭建流复制
搭建逻辑复制
关于 PUBLICATION
关于SUBSCRIPTION
逻辑复制的注意事项
复制槽运维
关于物理复制槽
关于逻辑复制槽
搭建主从流复制会遇到从库中接收不到主库被移除的日志情况,由于主库并不会去确认从库是否接收到日志,便将已经应用的WAL日志进行归档或者回收,就会导致从库在宕机一段时间再启动时,从主库找不到连续的WAL日志,而无法正常运行。
此时我们可以使用复制槽方法,这样在从库还未接收的WAL日志,主库便不会将其回收或归档。
复制槽分为物理复制槽physical replication slot(用于流复制)和逻辑复制槽logic replication slot(用于逻辑复制)。
关于流复制详细介绍
异步流复制
同步流复制
IP | 数据路径 | 端口 | |
主库 | 10.0.0.200 | /home/postgres/pgdata/data | 15432 |
从库 | 10.0.0.199 | /home/postgres/standby2 | 15432 |
pg_basebackup -h 10.0.0.200 -U r1 -F p -P -X stream -R -D standby2/ -p 15432
启动从库
在主库中创建物理复制槽
SELECT pg_create_physical_replication_slot('standby2');
使用以下视图 可以查看复制槽的使用情况
select * from pg_replication_slots ;--查看复制槽使用的情况
在从库中应用次复制槽 修改配置文件 /home/postgres/standby2/postgresql.auto.conf
primary_slot_name='standby2'
primary_conninfo = 'user=r1 passfile=''/home/postgres/.pgpass'' channel_binding=disable host=10.0.0.200 port=15432 sslmode=disable sslcompression=0 sslsni=1 ssl_min_protocol_version=TLSv1.2 gssencmode=disable krbsrvname=postgres target_session_attrs=any'
~
重新加载以下参数
pg_ctl -D standby2/ reload
此时主库查看复制槽状态,active变为t成为活跃状态
关于逻辑复制的详细介绍请关注
IP | 数据路径 | 端口 | |
主库 | 10.0.0.200 | /home/postgres/pgdata/data | 15432 |
从库 | 10.0.0.199 | /home/postgres/pg | 25432 |
主库中参数配置
wal_level = logcial --逻辑复制需要此参数在logcial 以上等级
synchronous_standby_names --这个参数在逻辑复制槽中也会有影响,打开这个参数
并设定相应的值,对应的发布端和订阅段也会形成一个强同步的状态,可以指定ANY的复制槽 也可以指定first num 多个的复制槽 关于这个参数的参数在同步流复制中有做讲解,此时不再累叙述 ,本文不打开此参数,以异步的情况做讲解。
synchronous_commit --此参数 关于这个参数的参数在同步流复制中有做讲解,此时不再累叙
注:在逻辑复制中,以上两个参数会影响到逻辑复制两端的同步时间差,两个参数不同的参数值配置,会影响对表操作的待机时长,让我们对性能形成误判。
相关语法介绍
--订阅的语法
CREATE SUBSCRIPTION subscription_name
CONNECTION 'conninfo'
PUBLICATION publication_name [, ...]
[ WITH ( subscription_parameter [= value] [, ... ] ) ]
--发布的语法
CREATE PUBLICATION name
[ FOR ALL TABLES
| FOR publication_object [, ... ] ]
[ WITH ( publication_parameter [= value] [, ... ] ) ]
where publication_object is one of:
TABLE [ ONLY ] table_name [ * ] [ ( column_name [, ... ] ) ] [ WHERE ( expression ) ] [, ... ]
TABLES IN SCHEMA { schema_name | CURRENT_SCHEMA } [, ... ]
这里讲几个总要的参数
FOR ALL TABLES
将发布标记为复制数据库中所有表(包括将来创建的表)的更改的发布
WITH (
publication_parameter
[= value
] [, ... ] )
此子句指定发布的可选参数。支持以下参数:
此参数确定新发布将向订阅服务器发布哪些 DML 操作。该值是以逗号分隔的操作列表。允许的操作是insert
, update
和delete、truncate
。默认值是发布所有操作,因此此选项的默认值为 。'insert, update, delete, truncate' --11版本后支持truncate操作
WITH (
subscription_parameter
[= value
] [, ... ] )
该子句指定订阅的可选参数。支持的参数有:
copy_data
(boolean
)
指定在复制启动后是否应复制正在订阅的发布中的现有数据。 默认值是true
。
create_slot
(boolean
)
指定该命令是否要在发布者上创建复制槽。默认值是true
。
enabled
(boolean
)
指定订阅是否应该主动复制,或者是否应该只是设置,但尚未启动。 默认值是true
。
slot_name
(string
)
要使用的复制插槽的名称。默认行为是使用订阅名称作为插槽的名称。
当slot_name
设置为NONE
时, 将不会有复制槽与订阅关联。这在需要稍后手动设置复制槽的情况下会使用。 这样的订阅必须同时enabled
并且 create_slot
设置为false
。
synchronous_commit
(enum
)
在这个订阅的应用worker进程时,该参数的值会覆盖synchronous_commit设置。 默认值是off
。
对于逻辑复制使用off
是安全的: 如果订阅者由于缺少同步而丢失事务,数据将从发布者再次发送。
进行同步逻辑复制时,不同的设置可能是合适的。 逻辑复制工作者向发布者报告写入和刷新的位置,当使用同步复制时, 发布者将等待实际刷新。这意味着,当订阅用于同步复制时, 将订阅者的synchronous_commit
设置为off
可能会增加发布服务器上COMMIT
的延迟。 在这种情况下,将synchronous_commit
设置为 local
或更高是有利的。
binary
(boolean
)
指定订阅是否要求发布器以二进制格式(相对的是文本格式)发送数据。 默认值是false
。 即使此选项被启用,也只有具备二进制发送和接收函数的数据类型将以二进制传输。
在进行跨版本复制时,可能会出现发布器具有某些数据类型的二进制发送函数,但订阅器缺乏针对此类型的二进制接收函数的情况。 在这种情况下,数据传输将失败,并且binary
选项不能被使用。
connect
(boolean
)
指定CREATE SUBSCRIPTION
是否应该连接到发布者。 将其设置为false
将会改变默认值enabled
、 create_slot
和copy_data
为false
。
不允许将connect
设置为false
的同时将 enabled
、create_slot
或copy_data
设置为true
。
因为该选项设置为false
时不会建立连接, 因此表没有被订阅,所以当启用订阅后,不会复制任何内容。 需要运行ALTER SUBSCRIPTION ... REFRESH PUBLICATION
才能订阅表。
streaming
(boolean
)
指定是否对此订阅启用进行中事务的流。 默认情况下,所有事务都在发布器上完全解码,直到那时才作为整体发送给订阅器。
创建发布
---创建 测试表
create table pg_text (id serial); --从库也需要创建一个表同名,schema同名,字段同名的表,表的结构从库创建的表字段可以多,可以少,数据类型可以不一样,但是需要是二进制兼容的数据类型
-- 主库创建一个发布
create publication pub_pg_text for table pg_text;
--从库创建一个订阅
create subscription sub_pg_text CONNECTION 'host=10.0.0.200 port=15432' publication pub_pg_text;
--主库参看复制槽
select * from pg_stat_replication_slots ; --基于postgresql-15版本,当主库的发布被从库订阅后,在主库上会自动创建一个与从库订阅名同名的复制槽,并开启使用
--主库查看哪些表有被创建发布端口
select * from pg_publication_tables ;
--从库上查看正在接收远端发布的进程号
select * from pg_stat_subscription;
当主库中表被从库订阅时,主库会迅速创建一个与订阅名同名的复制槽并启用,
主库中查看哪些表被发布
select * from pg_publication_tables ;
备注:当表在主库中被删除后 复制槽会仍然存在,重新建表也不会和旧的复制槽,旧的订阅端再一一对应,以下是主库删掉pg_text表 后的展示,此时从库会仍然保留,此时可以重新订阅,在订阅的参数配置中可以指定对应的复制槽。
1、DDL操作不支持复制,发布节点上发布表进行DDL操作后,DDL操作不会复制到订
阅节点,需要在订阅节点对发布表手动执行DDL操作。
2、序列本身不支持复制,当前逻辑复制仅支持普通表,序列、视图、物化视图、分区
表、外部表等对象都不支持。
3、TEMPORARY表和UNLOGGED表不会被复制。
4、大对象(Large Object)字段不支持复制。
5、表名与列名必须结构相同,列的数据类型也必须相同(除非类型隐式转换相同)。
6、订阅端的表可以有更多的列,并且顺序可以不同,但是类型和列名必须相同。
7、只有超级用户才有权限添加所有表。
8、不支持双向复制。
9、表必须有主键或者唯一约束,否则像UPDATE或者DELETE这样的操作无法被复制
当创建了复制槽没有在使用时
select pg_create_physical_replication_slot('txt'); --创建一个测试物理复制槽
通过表查看复制槽状态
select * from pg_replication_slots ;
当active字段为f(false)表示该物理复制槽并未被启用 便可以删掉
使用以下函数删除
select pg_drop_replication_slot('txt');
此时的复制就会消失掉。
由于逻辑复制槽是被订阅时,会创建一个和订阅同名的逻辑复制槽当主库中表被删除后,复制槽仍然存在且处于活跃状态,并且每一个publication 会fork一个进程,极大占用系统的性能,我们便需要将无用的复制槽给删掉
可以通过以下表查看有为哪些表创建了发布
select * from pg_publication_tables ;
创建一个测试表和发布
--主库
create table txt01(id int);
create publication pub_txt01 for table txt01 ;
--从库
create table txt01(id int);
create subscription sub_txt CONNECTION 'host=10.0.0.198 port=5432' publication pub_txt01;
此时逻辑复制槽为活跃状态,模拟我们不再需要这个映射关系 , 我在发布端将这个表删除后
删除表之后, pg_publication_tables 视图将不再有该表发布信息
此时逻辑复制的fork起来的work进程并没有退掉。
此时的复制槽仍然为活跃状态
在订阅端,删掉无用的订阅后,发布端的复制槽也会随着被移除
drop subscription sub_txt;
可以通过以下视图或表进行无效发布订阅的排查
--主
select * from pg_publication;
--从
select * from pg_subscription;
--对比是否所有的发布都有被订阅 ,删除没有订阅的发布;
--主
select * from pg_publication_tables ;
select * from pg_publication;
--对比是否所有的发布表都存在,删除表已经被移除的发布