【Vastbase G100】发布订阅功能详解与配置案例
2026-03-11 16:57 狂澜与玉昆0950 阅读(128) 评论(0) 收藏 举报1. 概述
发布订阅基于逻辑复制实现的数据同步功能,允许一个或多个订阅者订阅发布者节点上的一个或多个发布,订阅者从它们所订阅的发布拉取数据,实现跨节点的数据实时同步。
核心特性:
- 发布者上的更改会被实时发送给订阅者。订阅者以与发布者相同的顺序应用那些数据,这样在一个订阅中能够保证发布的事务一致性。
- 订阅者数据库的行为与任何其他vastbase实例相同,也可以定义自己的发布,成为其他数据库的发布者,支持基于该模式实现级联发布订阅。
- 订阅者可以被应用程序视为只读数据库,此时单个订阅内不会产生冲突;如果应用程序或其他订阅者在同一组表上执行写操作,则可能发生冲突。
2. 工作原理
逻辑复制原理:
- 发布端通过逻辑解码反解xlog生成逻辑日志,目标数据库解析逻辑日志以实时进行数据复制。

发布订阅流程:

3. 注意事项
- 发布端和订阅端的Vastbase G100数据库版本需保持一致。
- 调用者必须拥有该表的所有权。FOR ALL TABLES 子句要求调用者是具有 SYSADMIN 权限用户。
- 对象必须被明确地加入到发布,除非发布是用ALL TABLES创建的。
- 发布可自定义同步的操作类型(INSERT/UPDATE/DELETE 任意组合),默认所有操作类型都会被复制。
- 添加到发布 UPDATE 或 DELETE 操作的发布的表必须已经定义了 REPLICA IDENTITY,否则将在这些表上禁止这些操作。
- 如果有主键,复制标识就是主键。
- 如果表没有合适的键,可以设置成复制标识“full”(整行作为标识,执行alter table tablename replica identity full;),即整个行都成为键,但这样效率很低。
- 如果发布者端设置了非“full”的复制标识(主键 / 唯一索引),订阅者端也必须设置一个复制标识,且订阅端标识列需为发布端标识列的相同列或子集。
- 现有的发布不能启用或禁用 DDL 复制。
- 发布端和订阅端的 schema 必须一致。
4. 风险项
- 暂无
5. 配置案例
5.1 环境准备

5.2 发布者端配置
5.2.1 检验数据库参数
发布端需将 wal_level 参数设置为logical(支持逻辑复制),同时修改 synchronous_standby_names 参数,只保留数据库架构中的机器,避免第三方同步工具采用逻辑复制时被认为是备机,同步异常时阻塞主数据库。修改这两个参数后需重启数据库生效。
-- 查看参数当前值 vsql -c "show wal_level; show synchronous_standby_names;" -- 修改参数 wal_level vb_guc set -I all -N all -c "wal_level='logical'" -- 修改参数 synchronous_standby_names -- 主备/一主一备一仲裁: vb_guc set -I all -N all -c "synchronous_standby_names='ANY 2(dn_6001,dn_6002)'' -- 一主两备集群: vb_guc set -I all -N all -c "synchronous_standby_names='ANY 3(dn_6001,dn_6002,dn_6003)'' 数据库重启生效(根据实际部署环境执行重启命令) -- 单机 数据库关闭:root用户执行:stystemctl stop vastbase 数据库启动:root用户执行:stystemctl start vastbase -- 主备 数据库关闭: 备节点root用户执行:stystemctl stop vastbase 主节点root用户执行:stystemctl stop vastbase 数据库启动: 主节点root用户执行:stystemctl start vastbase 备节点root用户执行:stystemctl start vastbase -- HAS 1.x 关闭各节点Has服务,按异步备-同步备-主节点顺序依次关闭: systemctl stop has 启动各节点Has服务,按主节点-同步备-异步备顺序依次关闭: systemctl start has -- HAS 3.x 集群关闭:cm_ctl stop 集群启动:cm_ctl start -- 验证参数是否修改成功 vsql -c "show wal_level; show synchronous_standby_names;"

5.2.2 创建测试表
在发布者数据库上创建带主键的测试表(employee员工表、department部门表),并插入初始数据,主键将作为默认复制标识:
-- 登录发布者数据库 vsql -d postgres -p 5432 -r -- postgres 是数据库,根据实际情况替换 -- 创建测试表 CREATE TABLE employee ( id INTEGER PRIMARY KEY, name VARCHAR(50), department VARCHAR(50), salary NUMERIC, update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE department ( dept_id INTEGER PRIMARY KEY, dept_name VARCHAR(50) NOT NULL, location VARCHAR(100) ); -- 插入初始数据 INSERT INTO department VALUES (1, '研发部', 'A座5层'), (2, '市场部', 'B座3层'); INSERT INTO employee VALUES (1001, '张三', '研发部', 15000, now()), (1002, '李四', '市场部', 12000, now());

5.2.3 创建发布
创建名为my_publication的发布,显式关联employee和department两张表,默认同步 INSERT/UPDATE/DELETE 所有操作和 DDL 操作:
-- 创建发布,发布两个表 CREATE PUBLICATION my_publication FOR TABLE employee, department with (ddl='table'); -- 查看已创建的发布 SELECT * FROM pg_publication;

5.2.4 配置连接权限
创建具备 SYSADMIN 权限的复制用户,并在pg_hba.conf中配置订阅端的复制连接权限,允许订阅端通过该用户连接发布端:
-- 创建复制用户 CREATE USER repl_user WITH PASSWORD 'replication@123' sysadmin; -- 在pg_hba.conf中添加复制连接权限(需在操作系统层面操作) gs_guc reload -I all -N all -h "host replication repl_user 192.168.124.171/32 sha256"


5.3 订阅者端配置
5.3.1 创建相同表结构
在订阅者数据库上创建相同的表结构(逻辑复制不会同步DDL操作,需要先将发布端表结构迁移到订阅端):
方式一:手动创建表结构
-- 登录订阅者数据库 vsql -d postgres -p 5432 -r -- 创建相同的表结构 CREATE TABLE employee ( id INTEGER PRIMARY KEY, name VARCHAR(50), department VARCHAR(50), salary NUMERIC, update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE department ( dept_id INTEGER PRIMARY KEY, dept_name VARCHAR(50) NOT NULL, location VARCHAR(100) );
注意:列名需要匹配,但列顺序可以不同,数据类型也不必完全相同,只要能进行文本形式的转换即可。目标表还可以包含发布表中不存在的额外列,这些列将使用默认值填充。
方式二:用逻辑导出导入功能创建表结构:
# 在订阅者端执行,从发布者导入表结构 vb_dump postgres -h 192.168.124.170 -p 5432 -U repl_user -s -t employee -t department > ddl.sql # 删除或注释 ddl.sql 文件中发布的创建语句(避免订阅端创建重复发布) # 导入表结构到订阅者 vsql -d postgres -p 5432 -f ddl.sql



5.3.2 密码加密
-- 创建订阅前,需要在订阅端执行密码加密(在操作系统命令行执行) gs_guc generate -S replication@123 -D $GAUSSHOME/bin -o subscription
5.3.3 创建订阅
在订阅者端创建名为my_subscription的订阅,关联发布端的my_publication:
-- 创建订阅 CREATE SUBSCRIPTION my_subscription CONNECTION 'host=192.168.124.170 port=5433 user=repl_user dbname=postgres password=replication@123' PUBLICATION my_publication WITH ( enabled = true, slot_name = 'my_subscription_slot', synchronous_commit = 'off', binary = false );
参数说明:
- **subscription_name**:订阅名称,在数据库中唯一
- **CONNECTION**:连接发布端的字符串,包含IP地址、端口、数据库、用户名和密码
- **port**:必须使用主端口+1(即5433),否则会与线程池冲突
- **user/password**:需具有SYSADMIN或OPRADMIN权限
- **PUBLICATION**:要订阅的发布名称,一个订阅可对应多个发布
- **WITH选项**:
- **enabled**:指定订阅是否主动复制,默认为true
- **slot_name**:复制插槽名称,默认使用订阅名称
- **synchronous_commit**:覆盖synchronous_commit设置,逻辑复制通常设为off
- **binary**:是否以二进制格式发送数据,默认为false
5.3.4 查看订阅状态
-- 查看订阅信息 SELECT * FROM pg_subscription; -- 查看复制进度 SELECT * FROM pg_stat_subscription;

5.4 验证复制功能
订阅创建成功后,分别测试历史数据同步、INSERT/UPDATE/DELETE 操作同步、DDL更新同步,验证数据是否能从发布端实时同步至订阅端。
5.4.1 历史数据库的同步
-- 订阅者执行 SELECT * FROM department; SELECT * FROM employee;

预期结果:订阅端的查询结果与发布端初始数据完全一致。
5.4.2 测试数据插入
在发布者端插入新数据:
-- 发布者执行 INSERT INTO department VALUES (3, '财务部', 'A座8层'); INSERT INTO employee VALUES (1003, '王五', '财务部', 18000, now());
在订阅者端查询,验证数据是否同步:
-- 订阅者执行(稍等片刻) SELECT * FROM department; SELECT * FROM employee;

预期结果:订阅端能查询到发布端新增的数据。
5.4.3 测试数据更新
在发布者端更新数据:
-- 发布者执行 UPDATE employee SET salary = 20000 WHERE id = 1003;
在订阅者端验证更新是否生效。
-- 订阅者执行(稍等片刻) SELECT * FROM employee;
预期结果:订阅端中数据已更新。
5.4.4 测试数据删除
在发布者端删除数据:
-- 发布者执行 DELETE FROM employee WHERE id = 1001;
在订阅者端验证删除是否同步。
-- 订阅者执行(稍等片刻) SELECT * FROM employee;

预期结果:订阅端中数据已被删除。
5.4.5 测试DDL变化
在发布者端修改表结构,使其增加一列:
-- 发布者执行 ALTER TABLE employee add column address varchar(100);
在订阅者端验证DDL变更是否同步。
-- 订阅者执行 -- 查询表结构 \d+ employee

预期结果:订阅端中DDL已更新。
6. 发布订阅管理和运维
6.1 发布管理
支持修改发布的关联表、删除发布等操作,命令如下:
-- 修改发布的信息:用指定的表替换当前发布的表。 ALTER PUBLICATION my_publication SET TABLE product, department; -- 修改发布的信息:为发布中添加一个或多个表。 ALTER PUBLICATION my_publication ADD TABLE product; -- 修改发布的信息:从发布中删除一个或多个表。 ALTER PUBLICATION my_publication DROP TABLE employee; -- 删除发布(需先确保订阅端已删除对应订阅,避免残留复制槽) DROP PUBLICATION my_publication;
6.2 订阅管理
支持修改订阅连接信息、激活 / 停用订阅、刷新订阅、删除订阅等操作,命令如下:
-- 修改订阅的发布端连接信息 ALTER SUBSCRIPTION my_subscription CONNECTION 'host=192.168.1.11 port=5433 user=repl_user dbname=postgres password=replication@123'; -- 激活订阅(若创建时设置enabled = false,需手动激活) ALTER SUBSCRIPTION my_subscription SET (enabled = true); -- 刷新订阅(发布端新增/移除同步表后,订阅端执行刷新以同步表关联关系和初始数据) ALTER SUBSCRIPTION my_subscription REFRESH PUBLICATION; -- 删除订阅(同时自动删除发布端的对应复制槽) DROP SUBSCRIPTION my_subscription;

6.3 发布订阅运维
Vastbase G100提供多个视图用于监控发布端和订阅端的复制状态:
视图名称 执行节点 核心作用
pg_replication_slots 发布者 查看复制槽状态(是否活跃、未读取日志量等)
pg_stat_replication 发布者 查看发布端数据发送进度、网络连接状态
pg_publication 发布者 查看发布的基本信息(操作类型等)
pg_subscription 订阅者 查看订阅的基本信息(连接信息、关联发布等)
pg_stat_subscription 订阅者 查看订阅端应用进度、复制延迟、同步状态
-- 查询发布名称和对应表 SELECT pub.pubname, n.nspname AS schema_name, c.relname AS table_name FROM pg_publication_rel pr JOIN pg_publication pub on pr.prpubid = pub.oid JOIN pg_class c ON pr.prrelid = c.oid JOIN pg_namespace n ON c.relnamespace = n.oid; -- 查询订阅名称和对应表 SELECT sub.subname, n.nspname AS schema_name, c.relname AS table_name, (case sr.srsubstate when 'i' then '初始化' when 'd' then '基础数据正在复制' when 'f' then '基础数据复制完成' when 's' then '已与增量复制进度同步' when 'r' then '准备好增量复制' end) as "订阅状态" FROM pg_subscription_rel sr JOIN pg_subscription sub on sr.srsubid = sub.oid JOIN pg_class c ON sr.srrelid = c.oid JOIN pg_namespace n ON c.relnamespace = n.oid;
7. FAQ

我报路长嗟日暮,学诗谩有惊人句。
九万里风鹏正举。风休住,蓬舟吹取三山去!
浙公网安备 33010602011771号