流计算 Oceanus Postgres 连接器

Postgres 连接器支持从 PostgreSQL 数据库读取快照数据与增量 WAL 数据,并提供整库同步能力。通过 YAML 作业定义即可完成一条数据同步链路。

相关产品
流计算 Oceanus 产品页,含版本规格、价格与购买入口。

一、前置准备

使用前,需要在 PostgreSQL 侧完成以下 6 步。示例中的 <db>、<schema>、<table>、<user>、<password>、<slot_name> 请替换为实际值。

二、1. 开启逻辑解码

连接器通过逻辑解码从 WAL 中读取行级变更(INSERT / UPDATE / DELETE),需要将 wal_level 设为 logical。

查看当前配置:

SHOW wal_level; — 必须为 logicalSHOW max_replication_slots; — 复制槽总数上限SHOW max_wal_senders; — WAL 发送进程数上限

自建 PostgreSQL:

ALTER SYSTEM SET wal_level = logical;ALTER SYSTEM SET max_replication_slots = 10;ALTER SYSTEM SET max_wal_senders = 10;

修改 wal_level 后必须重启实例才能生效(该操作可能导致服务中断)

云数据库 PostgreSQL:在控制台的实例参数设置中,将 wal_level 改为 logical,然后重启实例(该操作可能导致服务中断)。

max_replication_slots 应不小于本实例上的 CDC 作业数与其他逻辑订阅数之和,并留出余量;max_wal_senders 应不小于 max_replication_slots。

三、2. 确认逻辑解码插件

逻辑解码插件将 WAL 转换为连接器可读取的格式,通过 decoding.plugin.name 指定,支持以下两种:

插件 是否需要安装 说明
pgoutput(默认) 不需要,PostgreSQL 10 及以上内置 推荐。需要先 创建 publication(第4步)
decoderbufs 需要编译安装,并配置 shared_preload_libraries 后重启 –

使用默认的 pgoutput 时无需安装。可通过创建测试复制槽确认插件可用,确认后立即删除:

SELECT pg_create_logical_replication_slot('oceanus_check_slot', 'pgoutput');SELECT pg_drop_replication_slot('oceanus_check_slot');

四、3. 创建同步账号并授权

建议创建专用的同步账号,无需超级用户权限。以下语句由高权限账号(自建库为 superuser,云数据库为控制台创建的高权限账号)执行:

— 创建账号。REPLICATION 用于建立复制连接、创建和读取复制槽CREATE ROLE <user> WITH LOGIN REPLICATION PASSWORD '<password>';– 连接目标库GRANT CONNECT ON DATABASE <db> TO <user>;– 访问 schemaGRANT USAGE ON SCHEMA <schema> TO <user>;– 全量快照读取:授权整个 schema,或只授权要同步的表GRANT SELECT ON ALL TABLES IN SCHEMA <schema> TO <user>;– 或:GRANT SELECT ON <schema>.<table1>, <schema>.<table2> TO <user>;– 可选:之后新建的表自动授予 SELECT(<table_owner> 为建表账号)ALTER DEFAULT PRIVILEGES FOR ROLE <table_owner> IN SCHEMA <schema> GRANT SELECT ON TABLES TO <user>;

权限 用途 缺少时的现象
LOGIN 登录数据库 无法连接
REPLICATION 建立复制连接、创建复制槽、读取增量 增量阶段连接失败
CONNECT ON DATABASE 连接目标库 无法连接目标库
USAGE ON SCHEMA 访问 schema 下的对象 找不到表
SELECT ON TABLE 读取全量快照 快照阶段报权限错误

验证:

SELECT rolname, rolcanlogin, rolreplication FROM pg_roles WHERE rolname = '<user>';– rolcanlogin 和 rolreplication 都应为 t

五、4. 创建 publication(使用 pgoutput 时必须)

pgoutput 只输出 publication 中所含表的变更。连接器默认使用名为 dbz_publication 的 publication,不存在时会尝试自动创建包含全库所有表的 publication,该操作需要超级用户权限。建议由高权限账号预先创建。

— 推荐:只发布需要同步的表CREATE PUBLICATION dbz_publication FOR TABLE <schema>.<table1>, <schema>.<table2>;– 之后新增同步表ALTER PUBLICATION dbz_publication ADD TABLE <schema>.<new_table>;

FOR TABLE 方式需要执行账号对目标库有 CREATE 权限,且为表的 owner;FOR ALL TABLES 方式需要超级用户(云数据库为 tencentdb_superuser)。

不建议使用 FOR ALL TABLES。库中无主键且未设置 REPLICA IDENTITY 的表,执行 UPDATE / DELETE 时会报错(cannot update table … because it does not have a replica identity and publishes updates),影响源库业务。

publication 需覆盖 tables 匹配到的所有表。未包含的表只能读到全量数据,读不到增量数据。

验证:

SELECT * FROM pg_publication_tables WHERE pubname = 'dbz_publication';

如需让不同作业使用不同的 publication,可配置 debezium.publication.name。

六、5. 设置表的 REPLICA IDENTITY(按需)

REPLICA IDENTITY 决定 UPDATE / DELETE 时 WAL 中记录的旧行内容。

取值 WAL 中记录的旧行内容 适用场景
DEFAULT(默认) 仅主键列 表有主键,且下游是主键表(如 Doris 主键模型)。一般不用修改
FULL 整行所有列 无主键表;或下游需要完整的 UPDATE 前镜像
NOTHING 不记录 不能用于 CDC

— 需要时设为 FULL。会增加 WAL 体积,大表或高频更新的表需评估ALTER TABLE <schema>.<table> REPLICA IDENTITY FULL;

验证:

SELECT relname, relreplident — d=default, f=full, n=nothing, i=indexFROM pg_classWHERE relnamespace = '<schema>'::regnamespace AND relkind IN ('r', 'p');

七、6. 确认网络连通

·云数据库 PostgreSQL:在安全组中放通 Oceanus 集群网段访问 5432 端口。

·自建 PostgreSQL:在 pg_hba.conf 中允许 Oceanus 网段连接目标数据库,然后执行 SELECT pg_reload_conf(); 重新加载。

八、复制槽(slot.name)

·无需手动创建。作业首次启动时自动创建,账号需具备 REPLICATION 属性。

·名称只能包含小写字母、数字和下划线,不超过 63 个字符。

·每个作业必须使用独立的复制槽。多个作业共用一个复制槽会导致数据丢失或读取异常。

九、版本说明

Flink 版本 说明
1.20 基于 Flink-cdc 社区 release-3.6 开发,JDK 版本为 11,支持 PostgreSQL 数据库

十、使用范围

可作为 Source(type: postgres)使用,不支持作为 Sink。

暂不支持同步表结构变更。PostgreSQL 的 WAL 日志中不包含可解析的表结构变更记录,因此上游发生 DDL 变更时不会传递到下游。

十一、Postgres 同步到 Doris

source: type: postgres name: Postgres Source hostname: 127.0.0.1 port: 5432 username: postgres password: pass tables: adb.\\.*.\\.* decoding.plugin.name: pgoutput slot.name: pgtestsink: type: doris name: Doris Sink fenodes: 127.0.0.1:8030 username: root password: passpipeline: name: Postgres to Doris Pipeline parallelism: 4

十二、Source 配置项

参数 是否必填 默认值 类型 说明
hostname required (none) String PostgreSQL 数据库服务器的 IP 地址或主机名。
port optional 5432 Integer PostgreSQL 数据库服务器的端口号。
username required (none) String 连接 PostgreSQL 数据库服务器时使用的用户名。
password required (none) String 连接 PostgreSQL 数据库服务器时使用的密码。
tables required (none) String 需要捕获的表名,格式为 库名.模式名.表名,支持正则表达式,多条规则用英文逗号分隔。注意:点号(.)是库名、模式名与表名的分隔符,如果需要在正则表达式中用点号匹配任意字符, 必须用反斜杠转义。例如:db0.\\.*.\\.*, db1.public.user_table_[0-9]+所有表名必须使用同一个 database,否则作业启动校验失败。若按该规则匹配不到任何表,作业启动时会直接报错。
slot.name required (none) String 为流式读取变更而在服务端创建的逻辑复制槽名称。每个作业应使用独立的复制槽。
decoding.plugin.name optional pgoutput String 服务端已安装的逻辑解码插件名称,可取 pgoutput 或 decoderbufs。
tables.exclude optional (none) String 需要排除的表名,在 tables 匹配结果之上做二次排除,用法与 tables 相同。排除后若无剩余表,作业启动校验失败。
server-time-zone optional (none) String 数据库服务器的会话时区,例如 Asia/Shanghai。未配置时使用作业运行环境的系统时区, 对时间相关字段可能造成数据不一致,建议显式配置。
table-id.include-database optional false Boolean 生成的 Table ID 是否包含 database 名。为 true 时格式为 (database, schema, table);为 false 时为 (schema, table)。
scan.startup.mode optional initial String 启动模式,可取 initial、latest-offset、 snapshot、committed-offset,详见「启动模式」章节。取值大小写不敏感。
scan.incremental.snapshot.chunk.size optional 8096 Integer 快照阶段单个 chunk 的行数。快照读取时表会被切分为多个 chunk。
scan.snapshot.fetch.size optional 1024 Integer 读取表快照时每次拉取的最大行数。
scan.incremental.snapshot.backfill.skip optional true Boolean 快照阶段是否跳过 backfill。跳过之后,快照期间发生的变更会在增量阶段回放, 而不是合并进快照结果。注意:跳过 backfill 可能带来数据不一致,只能保证 at-least-once 语义。
scan.lsn-commit.checkpoints-num-delay optional 3 Integer 开始提交 LSN 位点前延迟的 checkpoint 次数。增大该值后,全局复制槽消费到的位点会在多个 checkpoint 延迟之后才提交, 有利于在流式阶段持续回收日志文件。
schema-change.enabled optional false Boolean 是否在处理 pgoutput 的 Relation 消息时推断 CDC 列类型。
metadata.list optional (none) String 需要额外透传到下游的元数据列表,英文逗号分隔, 可取 op_ts、table_name、database_name、schema_name, 详见「支持的元数据列」章节。
connect.timeout optional 30s Duration 连接 PostgreSQL 服务器的超时时间。
connect.max-retries optional 3 Integer 建立 PostgreSQL 连接的最大重试次数。
connection.pool.size optional 20 Integer 连接池大小。
heartbeat.interval optional 30s Duration 发送心跳事件的间隔,用于跟踪最新可用的 WAL 位点。
chunk-meta.group.size optional 1000 Integer chunk 元数据的分组大小,超过该大小时元数据会被拆成多个分组。
chunk-key.even-distribution.factor.upper-bound optional 1000.0 Double chunk 切分键分布因子的上界。分布因子按 (MAX(id) – MIN(id) + 1) / rowCount 计算, 用于判断表数据是否均匀分布。取值必须大于等于 1.0。
chunk-key.even-distribution.factor.lower-bound optional 0.05 Double chunk 切分键分布因子的下界,取值必须落在 [0, 1] 区间内。
scan.incremental.close-idle-reader.enabled optional false Boolean 快照结束后是否关闭空闲的 Reader。依赖 FLIP-147(Checkpoints After Tasks Finished), Flink 版本需大于等于 1.14。
scan.incremental.snapshot.unbounded-chunk-first.enabled optional false Boolean 快照阶段是否优先分配 unbounded chunk,有助于降低 TaskManager 在快照阶段发生 OOM 的风险。
jdbc.properties.* optional (none) String 透传给 JDBC URL 的自定义属性,例如 jdbc.properties.ssl: 'true'。
debezium.* optional (none) String 透传给 Debezium Embedded Engine 的属性。

十三、启动模式

scan.startup.mode 决定作业从哪里开始读取数据,取值如下(大小写不敏感):

·initial(默认):首次启动时先对捕获的表做全量快照,快照完成后继续读取最新 WAL。

·latest-offset:跳过快照,只从 WAL 末尾开始读取,即只消费作业启动之后产生的变更。

·snapshot:只做快照阶段,不进入增量阶段,快照读取完成后作业退出。

·committed-offset:跳过快照,从复制槽中已确认提交的位点开始读取。

十四、支持的元数据列

通过 metadata.list 可以指定透传到下游的元数据,可在 transform 中直接引用。

Key 类型 说明
op_ts TIMESTAMP_LTZ(3) NOT NULL 该行数据在数据库中发生变更的时间。如果该记录读取自表的快照而非变更流,则该值始终为 0。
table_name STRING NOT NULL 包含该行数据的表名。
schema_name STRING NOT NULL 包含该行数据的 schema 名。
database_name STRING NOT NULL 包含该行数据的 database 名。

配置示例:

source: type: postgres metadata.list: op_ts,table_name,database_name,schema_name

十五、数据类型映射

Postgres 作为 Source 时,按下表把读取到的 PostgreSQL 字段类型转换为 CDC 类型。

PostgreSQL 类型 CDC 类型 说明
BOOLEAN BOOLEAN –
BIT(1)VARBIT(1) BOOLEAN –
BIT(n),n > 1VARBIT(n),n > 1 BINARY(n) –
SMALLINTINT2SMALLSERIALSERIAL2 SMALLINT –
INTEGERSERIAL INT –
BIGINTBIGSERIALOID BIGINT –
REALFLOAT4 FLOAT –
DOUBLE PRECISIONFLOAT8 DOUBLE –
NUMERIC(p, s)DECIMAL(p, s) DECIMAL(p, s) / DOUBLE / STRING 取决于 Debezium 的 decimal 处理模式:precise 模式下,精度在 (18, 38] 区间内映射为 DECIMAL(p, s), 否则(含未显式声明精度的情况)映射为 DECIMAL(38, 18);double 模式映射为 DOUBLE;string 模式映射为 STRING。
MONEY DECIMAL(38, s) s 由 Debezium 的 money 小数位数配置决定。
CHAR(n)CHARACTER(n)BPCHAR(n) CHAR(n) –
VARCHAR(n)CHARACTER VARYING(n) VARCHAR(n) –
TEXTPOINTUUIDJSONJSONBXMLINETCIDRMACADDRMACADDR8INT4RANGENUMRANGEINT8RANGETSRANGETSTZRANGEDATERANGELTREEGEOMETRYGEOGRAPHYCITEXT枚举类型 STRING PostGIS 的 GEOMETRY、GEOGRAPHY 类型以文本形式读出。
HSTORE STRING 或 MAP(STRING, STRING) 取决于 Debezium 的 hstore 处理模式:json 模式映射为 STRING, map 模式映射为 MAP(STRING, STRING)。
BYTEA BYTES 或 STRING 取决于 Debezium 的 binary 处理模式:bytes 模式映射为 BYTES, base64 / hex 模式映射为 STRING。
TIMESTAMP [(p)]TIMESTAMP WITHOUT TIME ZONE [(p)] TIMESTAMP [(p)] –
TIMESTAMPTZTIMESTAMP WITH TIME ZONE [(p)] TIMESTAMP_LTZ [(p)] 由 Debezium 归一化到 UTC 后按带本地时区的时间戳表示。
TIME [(p)]TIME WITHOUT TIME ZONE [(p)] TIME [(p)] –
DATE DATE –
INTERVAL BIGINT 或 STRING 取决于 Debezium 的 interval 处理模式:numeric 模式映射为 BIGINT(微秒数), string 模式映射为 STRING。
数组类型(如 INT4[]、TEXT[]) ARRAY(<元素类型>) 元素类型按上表规则转换,例如 INT4[] 映射为 ARRAY(INT), TEXT[] 映射为 ARRAY(STRING)。

未在上表中出现的字段类型暂不支持,同步包含此类字段的表会导致作业失败。

赞 (0)
上一篇 4天前
下一篇 4天前