openGauss/MogDB 从一开始就支持了逻辑复制,借助wal2json插件通过函数来实现对wal文件的逻辑解析,应用端通过指定接口来完成指定对象的DML操作变更使用;从3.0开始支持了发布订阅功能,可以实现将指定对象从一个数据库同步到另一个数据库,正常使用场景的发布订阅是应用在不同实例之间数据库的,对于同一个实例之间的不同数据库其实也是可以使用发布订阅功能的,也算是除了dblink和fdw之外,实现“跨库访问”的另一个选择。
前提
- 正常运行的数据库实例
- 参数wal_level=logical, 足够的max_replication_slots 和 max_wal_senders
- 准备两个数据库分别做为分布和订阅,这里是logical_s 和 logical_t
- 具有sysadmin 或 replcation,OPRADMIN 权限的用户,这里用repluser
配置发布订阅
检查数据库参数
wal_level、max_wal_senders、max_replication_slots 这三个参数修改,都需要重启数据库实例才能生效,生产数据库谨慎操作。
```
select name,setting from pg_settings where name in('wal_level','max_wal_senders','max_replication_slots');
name | setting
-----------------------+---------
max_replication_slots | 8
max_wal_senders | 16
wal_level | logical
```
#### 创建用户
```
create user repluser REPLICATION OPRADMIN encrypted password 'repluser@123';
```
#### 配置白名单
xxx.xxx.xxx.xxx 代表本机ip,建议使用集群内部ip
```
host replication repluser xxx.xxx.xxx.xxx/32 sha256
```
#### 添加发布者
发布者需要在logical_s数据库添加,本次准备同步dblog表
```
CREATE PUBLICATION mypub FOR TABLE dblog;
--3.1版本增加了初始化数据的功能,复制用户会对同步表的历史数据进行copy操作,需要将要同步表的查询权限给复制用户
grant select on table dblog to repluser;
```
#### 添加订阅者
订阅节点需要添加key文件,否则会提示ERROR: No key file subscription.key.cipher
```
gs_ssh -c "gs_guc generate -S repluser@123 -D $GAUSSHOME/bin -o subscription"
```
现在我们添加订阅者,会出现连接失败,原因是使用主端口会与线程池冲突,应该使用**主端口+1**
```
logical_t=# CREATE SUBSCRIPTION mysub CONNECTION 'dbname=logical_s host=xxx.xxx.xxx.xxx port=26000 user=repluser password=repluser@123' PUBLICATION mypub ;
WARNING: apply worker could not connect to the remote server
ERROR: could not connect to the publisher
```
修改端口号后再次添加,发现语句hang住了
```
logical_t=# CREATE SUBSCRIPTION mysub CONNECTION 'dbname=logical_s host=xxx.xxx.xxx.xxx port=26001 user=repluser password=repluser@123' PUBLICATION mypub ;
```
检查数据库日志,会发现以下信息,有事务waiting
```
LOG: create slot "pg_replslot/mysubt" on disk successfully
LOG: logical decoding found initial starting point at 4/BB2C54E0
[BACKEND] DETAIL: Waiting for transactions (approximately 1) older than 825548 to end.
```
查看锁阻塞信息,会发现create subscription语句阻塞了一个事务,而这个事务没有具体的query信息,是一个数据库内部事务,经排查这个内部事务的操作是创建复制槽。
```
locker_user | om302
locker_query_start | 2023-01-07 23:36:42.179012+08
locker_granted | t
locker_query | CREATE SUBSCRIPTION mysub CONNECTION ***************************************************************************************PUBLICATION mypub ;
locked_query |
locked_query_start |
locked_granted | f
locked_user | repluser
locked_times |
```
在不同实例创建发布订阅是不会出现这个lock信息的,既然问题与创建复制槽相关,那我们把创建订阅者的步骤做一下拆分:
```
- 先在目标数据库logical_t创建一个未启用的订阅者
logical_t=# CREATE SUBSCRIPTION mysub CONNECTION 'dbname=logical_s host=xxx.xxx.xxx.xxx port=26001 user=repluser password=repluser@123' PUBLICATION mypub with(enabled=false);
- 然后在原数据库logical_s手工添加一个逻辑复制槽mysub
logical_s=# select pg_create_logical_replication_slot('mysub','pgoutput');
- 目标数据库修改系统表,启动订阅者
logical_t=# update pg_subscription set subenabled='t' where subname='mysub';
- 为订阅者添加复制槽
logical_t=# alter subscription mysubt set(slot_name=mysub);
```
同步验证
总结
openGauss/MogDB的逻辑发布订阅功能不仅仅可以在不同实例数据库之间实现,也同样适用于同一个实例下的不同数据库,但由于内部事务锁的问题,需要将创建订阅者的步骤进行拆分手工处理。openGauss/MogDB 从一开始就支持了逻辑复制,借助wal2json插件通过函数来实现对wal文件的逻辑解析,应用端通过指定接口来完成指定对象的DML操作变更使用;从3.0开始支持了发布订阅功能,可以实现将指定对象从一个数据库同步到另一个数据库,正常使用场景的发布订阅是应用在不同实例之间数据库的,对于同一个实例之间的不同数据库其实也是可以使用发布订阅功能的,也算是除了dblink和fdw之外,实现“跨库访问”的另一个选择。
前提
- 正常运行的数据库实例
- 参数wal_level=logical, 足够的max_replication_slots 和 max_wal_senders
- 准备两个数据库分别做为分布和订阅,这里是logical_s 和 logical_t
- 具有sysadmin 或 replcation,OPRADMIN 权限的用户,这里用repluser
配置发布订阅
检查数据库参数
wal_level、max_wal_senders、max_replication_slots 这三个参数修改,都需要重启数据库实例才能生效,生产数据库谨慎操作。
```
select name,setting from pg_settings where name in('wal_level','max_wal_senders','max_replication_slots');
name | setting
-----------------------+---------
max_replication_slots | 8
max_wal_senders | 16
wal_level | logical
```
#### 创建用户
```
create user repluser REPLICATION OPRADMIN encrypted password 'repluser@123';
```
#### 配置白名单
xxx.xxx.xxx.xxx 代表本机ip,建议使用集群内部ip
```
host replication repluser xxx.xxx.xxx.xxx/32 sha256
```
#### 添加发布者
发布者需要在logical_s数据库添加,本次准备同步dblog表
```
CREATE PUBLICATION mypub FOR TABLE dblog;
--3.1版本增加了初始化数据的功能,复制用户会对同步表的历史数据进行copy操作,需要将要同步表的查询权限给复制用户
grant select on table dblog to repluser;
```
#### 添加订阅者
订阅节点需要添加key文件,否则会提示ERROR: No key file subscription.key.cipher
```
gs_ssh -c "gs_guc generate -S repluser@123 -D $GAUSSHOME/bin -o subscription"
```
现在我们添加订阅者,会出现连接失败,原因是使用主端口会与线程池冲突,应该使用**主端口+1**
```
logical_t=# CREATE SUBSCRIPTION mysub CONNECTION 'dbname=logical_s host=xxx.xxx.xxx.xxx port=26000 user=repluser password=repluser@123' PUBLICATION mypub ;
WARNING: apply worker could not connect to the remote server
ERROR: could not connect to the publisher
```
修改端口号后再次添加,发现语句hang住了
```
logical_t=# CREATE SUBSCRIPTION mysub CONNECTION 'dbname=logical_s host=xxx.xxx.xxx.xxx port=26001 user=repluser password=repluser@123' PUBLICATION mypub ;
```
检查数据库日志,会发现以下信息,有事务waiting
```
LOG: create slot "pg_replslot/mysubt" on disk successfully
LOG: logical decoding found initial starting point at 4/BB2C54E0
[BACKEND] DETAIL: Waiting for transactions (approximately 1) older than 825548 to end.
```
查看锁阻塞信息,会发现create subscription语句阻塞了一个事务,而这个事务没有具体的query信息,是一个数据库内部事务,经排查这个内部事务的操作是创建复制槽。
```
locker_user | om302
locker_query_start | 2023-01-07 23:36:42.179012+08
locker_granted | t
locker_query | CREATE SUBSCRIPTION mysub CONNECTION ***************************************************************************************PUBLICATION mypub ;
locked_query |
locked_query_start |
locked_granted | f
locked_user | repluser
locked_times |
```
在不同实例创建发布订阅是不会出现这个lock信息的,既然问题与创建复制槽相关,那我们把创建订阅者的步骤做一下拆分:
```
- 先在目标数据库logical_t创建一个未启用的订阅者
logical_t=# CREATE SUBSCRIPTION mysub CONNECTION 'dbname=logical_s host=xxx.xxx.xxx.xxx port=26001 user=repluser password=repluser@123' PUBLICATION mypub with(enabled=false);
- 然后在原数据库logical_s手工添加一个逻辑复制槽mysub
logical_s=# select pg_create_logical_replication_slot('mysub','pgoutput');
- 目标数据库修改系统表,启动订阅者
logical_t=# update pg_subscription set subenabled='t' where subname='mysub';
- 为订阅者添加复制槽
logical_t=# alter subscription mysubt set(slot_name=mysub);
```
同步验证
总结
openGauss/MogDB的逻辑发布订阅功能不仅仅可以在不同实例数据库之间实现,也同样适用于同一个实例下的不同数据库,但由于内部事务锁的问题,需要将创建订阅者的步骤进行拆分手工处理。