Postgres Connector
Postgres CDC Pipeline 连接器允许从 Postgres 数据库读取快照数据和增量数据,并提供端到端的整库数据同步能力。本文描述了如何设置 Postgres CDC Pipeline 连接器。
示例
从 Postgres 读取数据同步到 Fluss 的 Pipeline 可以定义如下:
source:
type: postgres
name: Postgres Source
hostname: 127.0.0.1
port: 5432
username: admin
password: pass
# 需要确保所有的表来自同一个database
tables: adb.\.*.\.*
decoding.plugin.name: pgoutput
slot.name: pgtest
schema-change.enabled: true
sink:
type: fluss
name: Fluss Sink
bootstrap.servers: localhost:9123
# Security-related properties for the Fluss client
properties.client.security.protocol: sasl
properties.client.security.sasl.mechanism: PLAIN
properties.client.security.sasl.username: developer
properties.client.security.sasl.password: developer-pass
pipeline:
name: Postgres to Fluss Pipeline
parallelism: 4
schema.change.behavior: lenient
连接器配置项
| Option | Required | Default | Type | Description |
|---|---|---|---|---|
| hostname | required | (none) | String | Postgres 数据库服务器的 IP 地址或主机名。 |
| port | optional | 5432 | Integer | Postgres 数据库服务器的整数端口号。 |
| username | required | (none) | String | 连接到 Postgres 数据库服务器时要使用的 Postgres 用户的名称。 |
| password | required | (none) | String | 连接 Postgres 数据库服务器时使用的密码。 |
| tables | required | (none) | String | 需要监视的 Postgres 数据库的表名。表名支持正则表达式,以监视满足正则表达式的多个表。 需要确保所有的表来自同一个数据库。 需要注意的是,点号(.)被视为数据库、模式和表名的分隔符。如果需要在正则表达式中使用点(.)来匹配任何字符,必须使用反斜杠对点进行转义。 例如,bdb.user_schema_[0-9].user_table_[0-9]+, bdb.schema_\.*.order_\.* |
| slot.name | required | (none) | String | 为从特定插件以流式传输方式获取某个数据库/模式的变更数据,所创建的 Postgre 逻辑解码槽(logical decoding slot)的名称。服务器使用这个槽(slot)将事件流式传输给你要配置的连接器(connector)。
复制槽名称必须符合 PostgreSQL 复制插槽的命名规则, 其规则如下:"Each replication slot has a name, which can contain lower-case letters, numbers, and the underscore character." |
| decoding.plugin.name | optional | (none) | String | The name of the Postgres logical decoding plug-in installed on the server. Supported values are decoderbufs and pgoutput. |
| tables.exclude | optional | (none) | String | 需要排除的 Postgres 数据库的表名,参数会在 tables 参数后发生排除作用。表名支持正则表达式,以排除满足正则表达式的多个表。 用法和 tables 参数相同 |
| server-time-zone | optional | (none) | String | 数据库服务器中的会话时区,例如:"Asia/Shanghai"。 它控制 Postgres 中的时间戳类型如何转换为字符串。 更多请参考 这里。 如果没有设置,则使用 ZoneId.systemDefault() 来确定服务器时区。 |
| scan.incremental.snapshot.chunk.size | optional | 8096 | Integer | 表快照的块大小(行数),读取表的快照时,捕获的表被拆分为多个块。 |
| scan.snapshot.fetch.size | optional | 1024 | Integer | 读取表快照时每次读取数据的最大条数。 |
| scan.startup.mode | optional | initial | String | Postgres CDC 消费者可选的启动模式, 合法的模式为 "initial","latest-offset","committed-offset" 和 ""snapshot"。 |
| scan.incremental.snapshot.backfill.skip | optional | false | Boolean |
是否在快照读取阶段跳过 backfill。 如果跳过 backfill,快照阶段捕获表的更改将在稍后的 wal log 读取阶段被回放,而不是合并到快照中。 警告:跳过 backfill 可能会导致数据不一致,因为快照阶段发生的某些 wal log 事件可能会被重放(仅保证 at-least-once)。 例如,更新快照阶段已更新的值,或删除快照阶段已删除的数据。这些重放的 wal log 事件应进行特殊处理。 |
| scan.lsn-commit.checkpoints-num-delay | optional | 3 | Integer | 在开始提交 LSN 偏移量之前,允许的检查点延迟次数。 检查点的 LSN 偏移量将以滚动方式提交,最早的那个检查点标识符将首先从延迟的检查点中提交。 |
| connect.timeout | optional | 30s | Duration | 连接器在尝试连接到 Postgres 数据库服务器后超时前应等待的最长时间。该时长不能少于 250 毫秒。 |
| connect.max-retries | optional | 3 | Integer | 连接器应重试以建立 Postgres 数据库服务器连接的最大重试次数。 |
| connection.pool.size | optional | 20 | Integer | 连接池大小。 |
| jdbc.properties.* | optional | 20 | String | 传递自定义 JDBC URL 属性的选项。用户可以传递自定义属性,如 'jdbc.properties.useSSL' = 'false'。 |
| heartbeat.interval | optional | 30s | Duration | 用于跟踪最新可用 wal committed offset 偏移的发送心跳事件的间隔。 |
| debezium.* | optional | (none) | String | 将 Debezium 的属性传递给 Debezium 嵌入式引擎,该引擎用于从 Postgres 服务器捕获数据更改。
例如:'debezium.snapshot.mode' = 'never'。
查看更多关于 Debezium 的 Postgres 连接器属性 |
| scan.incremental.close-idle-reader.enabled | optional | false | Boolean | 是否在快照结束后关闭空闲的 Reader。此特性需要 flink 版本大于等于 1.14 并且 'execution.checkpointing.checkpoints-after-tasks-finish.enabled' 需要设置为 true。 若 flink 版本大于等于 1.15,'execution.checkpointing.checkpoints-after-tasks-finish.enabled' 默认值变更为 true,可以不用显式配置 'execution.checkpointing.checkpoints-after-tasks-finish.enabled' = true。 |
| chunk-meta.group.size | optional | 1000 | String | 分块元数据的组大小,如果元数据大小超过该组大小,则元数据将被划分为多个组。 |
| metadata.list | optional | (none) | String | 源记录中可读取的元数据列表,将传递给下游并在转换模块中使用,各字段以逗号分隔。可用的可读元数据包括:op_ts、table_name、database_name、schema_name。详见支持的元数据列。 |
| scan.incremental.snapshot.unbounded-chunk-first.enabled | optional | false | String |
在快照读取阶段,是否优先分配无界分块。 这有助于降低在对最大无界分块进行快照时,TaskManager 发生内存溢出(OOM)错误的风险。 此为实验性选项,默认值为 false。 |
| table-id.include-database | optional | false | Boolean |
是否在生成的 Table ID 中包含数据库名称。 如果设置为 true,Table ID 的格式为(数据库,模式,表)。 如果设置为 false,Table ID 的格式为(模式,表)。 默认值为 false。 |
| scan.newly-added-table.enabled | optional | false | Boolean |
是否扫描新增的表。默认值为 false。
该选项仅在从 savepoint 或 checkpoint 恢复时生效,
会启用 SnapshotSplitAssigner#captureNewlyAddedTables() 代码路径,
以发现在 savepoint 时刻未被捕获但匹配 source tables 模式的新表。
|
| scan.pre-epoch-timestamp.wall-clock-conversion.enabled | optional | false | Boolean |
是否对 1970-01-01(epoch)之前的 PostgreSQL "timestamp without time zone" 列值,按照数据库中存储的日期时间(wall clock)进行转换。 开启后,该值不会受运行任务的 JVM 时区影响,这在存在历史时区偏移的时区下很重要:当 JVM 时区为 Asia/Shanghai 时, 数据库中存储的 "1900-01-01 00:00:00.123" 否则会被读取为 "1900-01-01 00:05:43.123"。 关闭(默认值)时保持原有的转换行为。1970-01-01 及之后的值无论是否开启该选项都会被同样地转换, 且该选项不会改变列的数据类型。 |
| schema-change.enabled | optional | false | Boolean |
是否开启 Postgres 源的 Schema 变更推导。开启后,连接器会通过对比 pgoutput Relation 消息与缓存的 Schema 来推导 Schema 变更事件(新增列、删除列、重命名列、修改列类型)。 需要将 decoding.plugin.name 设置为 pgoutput。默认值为 false。 |
注意:
- 配置选项
tables指定 Postgres CDC 需要采集的表,格式为db.schema1.tabe1,db.schema2.table2,其中所有的 db 需要为同一个 db,这是因为 postgres 链接 url 中需要指定 dbname,目前 cdc 只支持链接一个 db。
启动模式
配置选项 scan.startup.mode 指定 Postgres CDC 使用者的启动模式。有效枚举包括:
initial(默认):在连接器首次启动时,会对被监控的数据库表执行一次初始快照(snapshot),然后继续读取复制插槽中的变更事件。。latest-offset:在首次启动时不执行快照操作,而是直接从复制插槽的末尾开始读取,即只获取连接器启动之后发生的变更。committed-offset:跳过快照阶段,从复制插槽中已确认的 confirmed_flush_lsn 偏移量开始读取事件,即从上次提交的位置继续读取变更。snapshot: 只进行快照阶段,跳过增量阶段,快照阶段读取结束后退出。
可用的指标
指标系统能够帮助了解分片分发的进展,下面列举出了支持的 Flink 指标 Flink metrics:
| Group | Name | Type | Description |
|---|---|---|---|
| namespace.schema.table | isSnapshotting | Gauge | 表是否在快照读取阶段 |
| namespace.schema.table | isStreamReading | Gauge | 表是否在增量读取阶段 |
| namespace.schema.table | numTablesSnapshotted | Gauge | 已经被快照读取完成的表的数量 |
| namespace.schema.table | numTablesRemaining | Gauge | 还没有被快照读取的表的数据 |
| namespace.schema.table | numSnapshotSplitsProcessed | Gauge | 正在处理的分片的数量 |
| namespace.schema.table | numSnapshotSplitsRemaining | Gauge | 还没有被处理的分片的数量 |
| namespace.schema.table | numSnapshotSplitsFinished | Gauge | 已经处理完成的分片的数据 |
| namespace.schema.table | snapshotStartTime | Gauge | 快照读取阶段开始的时间 |
| namespace.schema.table | snapshotEndTime | Gauge | 快照读取阶段结束的时间 |
注意:
- Group 名称是
namespace.schema.table,这里的namespace是实际的数据库名称,schema是实际的 schema 名称,table是实际的表名称。
支持的元数据列
PostgreSQL CDC 连接器支持从源记录中读取元数据列。这些元数据列可以在转换操作中使用或传递给下游 Sink。
注意: 部分元数据信息也可以通过 Transform 表达式获取(例如 __namespace_name__、__schema_name__、__table_name__)。主要区别如下:
op_ts:仅可通过metadata.list获取 - 提供数据库中实际的操作时间戳。table_name、database_name、schema_name:可通过metadata.list或 Transform 表达式获取。使用metadata.list可以直接将这些值传递给下游 Sink,无需编写转换规则,对于基本用例更加简单。
要启用元数据列,请使用逗号分隔的元数据列名称列表配置 metadata.list 选项:
source:
type: postgres
# ... 其他配置
metadata.list: op_ts,table_name,database_name,schema_name
支持以下元数据列:
| 元数据列 | 数据类型 | 描述 |
|---|---|---|
| op_ts | BIGINT NOT NULL | 数据变更事件在数据库中发生的时间戳(自纪元以来的毫秒数)。对于快照记录,此值为 0。 |
| table_name | STRING NOT NULL | 包含变更行的表名称。替代方案:在 Transform 表达式中使用 __table_name__。 |
| database_name | STRING NOT NULL | 包含变更行的数据库名称。替代方案:在 Transform 表达式中使用 __namespace_name__。 |
| schema_name | STRING NOT NULL | 包含变更行的 Schema 名称。这是 PostgreSQL 特有的。替代方案:在 Transform 表达式中使用 __schema_name__。 |
使用示例:
source:
type: postgres
hostname: localhost
port: 5432
username: postgres
password: postgres
tables: mydb.public.orders
slot.name: flink_slot
metadata.list: op_ts,table_name,schema_name
transform:
- source-table: mydb.public.orders
projection: order_id, customer_id, op_ts, table_name, schema_name
description: 在输出中包含元数据列
数据类型映射
注意:由于 Debezium 版本不支持多维数组,目前只支持 PostgreSQL 的单维数组,如:'ARRAY[1,2,3]','int[]'。
Temporal types Mapping
除了包含时区信息的 PostgreSQL 的 TIMESTAMPTZ 数据类型之外,其他时间类型如何映射取决于连接器配置属性 debezium.time.precision.mode 的值。以下各节将描述这些映射关系:
- debezium.time.precision.mode=adaptive
- debezium.time.precision.mode=adaptive_time_microseconds
- debezium.time.precision.mode=connect
注意:受限当前 CDC 对时间类型 Time 的精度为 3,debezium.time.precision.mode 为 adaptive 或 adaptive_time_microseconds 或 connect Time 类型都转化为 Time(3) 类型。
debezium.time.precision.mode=adaptive
当 debezium.time.precision.mode 属性设置为默认的 adaptive(自适应)时,TIME 的精度为 3,TIMESTAMP 的精度为 6。
debezium.time.precision.mode=adaptive_time_microseconds
当 debezium.time.precision.mode 属性设置为默认的 adaptive_time_microseconds 时,TIME 的精度为 3,TIMESTAMP 的精度为 6。
debezium.time.precision.mode=connect
当 debezium.time.precision.mode 属性设置为默认的 connect 时,TIME 和 TIMESTAMP 的精度都为 3。
Decimal types Mapping
PostgreSQL 连接器配置属性 debezium.decimal.handling.mode 的设置决定了连接器如何映射十进制类型。
当 debezium.decimal.handling.mode 属性设置为 precise(精确)时,连接器会对所有 DECIMAL、NUMERIC 和 MONEY 列使用 Kafka Connect 的 org.apache.kafka.connect.data.Decimal 逻辑类型。这是默认模式。
当 debezium.decimal.handling.mode 属性设置为 double 时,连接器将所有 DECIMAL、NUMERIC 和 MONEY 值表示为 Java 的 double 值,并按照下表所示进行编码。
debezium.decimal.handling.mode 配置属性的最后一个可选设置是 string(字符串)。在这种情况下,连接器将 DECIMAL、NUMERIC 和 MONEY 值表示为其格式化的字符串形式,并按照下表所示进行编码。
当 debezium.decimal.handling.mode 的设置为 string 或 double 时,PostgreSQL 支持将 NaN(非数字)作为一个特殊值存储在 DECIMAL/NUMERIC 值中。在这种情况下,连接器会将 NaN 编码为 Double.NaN 或字符串常量 NAN。
HSTORE type Mapping
PostgreSQL 连接器配置属性 debezium.hstore.handling.mode 的设置决定了连接器如何映射 HSTORE 值。
当 debezium.hstore.handling.mode 属性设置为 json(默认值)时,连接器将 HSTORE 值表示为 JSON 值的字符串形式,并按照下表所示进行编码。当 debezium.hstore.handling.mode 属性设置为 map 时,连接器对 HSTORE 值使用 MAP 模式类型。
| PostgreSQL type | CDC type |
|---|---|
| HSTORE | STRING(`debezium.hstore.handling.mode`=`string`) |
| HSTORE | MAP(`debezium.hstore.handling.mode`=`map`) |
Network address types Mapping
PostgreSQL 拥有可以存储 IPv4、IPv6 和 MAC 地址的数据类型。使用这些类型来存储网络地址比使用纯文本类型更为合适。网络地址类型提供了输入错误检查以及专用的操作符和函数。
PostGIS Types Mapping
PostgreSQL 通过 PostGIS 扩展支持空间数据类型:
GEOMETRY(POINT, xx): 在笛卡尔坐标系中表示一个点,其中 EPSG:xx 定义了坐标系。它适用于局部平面计算。
GEOGRAPHY(MULTILINESTRING): 在基于球面模型的纬度和经度上存储多条线串。它适用于全球范围的空间分析。
前者适用于小范围的平面数据,而后者适用于需要考虑地球曲率的大范围数据。
| Spatial data in Postgres | Json String converted in Flink |
|---|---|
| GEOMETRY(POINT, xx) | {"coordinates":"[[174.9479, -36.7208]]","type":"Point","srid":3187}" |
| GEOGRAPHY(MULTILINESTRING) | {"coordinates":"[[169.1321, -44.7032],[167.8974, -44.6414]]","type":"MultiLineString","srid":4326} |
Copyright © 2026 The Apache Software Foundation. Apache Flink, Flink, and the Flink logo are trademarks of The Apache Software Foundation.