7.4. Debezium PostgreSQL 连接器如何映射数据类型

PostgreSQL 连接器代表对带有类似行存在的表的事件的行的更改。event 包含每个列值的字段。该值在事件中如何代表取决于该列的 PostgreSQL 数据类型。以下小节描述了连接器如何将 PostgreSQL 数据类型映射到事件 字段中的字面 类型和语义类型

  • literal type 代表值如何被代表,使用 Kafka Connect schema 类型:INT8, INT16, INT32, INT64, FLOAT32, FLOAT64, BOOLEAN, STRING, BYTES, ARRAY, MAP, 和 STRUCT
  • 语义类型 描述了 Kafka Connect 模式如何使用字段名称来捕获字段 的含义

如果默认数据类型转换无法满足您的需要,您可以为连接器 创建自定义转换器

详情包括在以下部分:

基本类型

下表描述了连接器如何映射基本类型。

表 7.12. PostgreSQL 基本数据类型的映射

PostgreSQL 数据类型字面类型(架构类型)语义类型(架构名称)和备注

布尔值

布尔值

不适用

BIT(1)

布尔值

不适用

BIT( > 1)

BYTES

io.debezium.data.Bits

length schema 参数包含一个代表位数的整数。生成的 byte[] 包含位(以 little-endian 格式),其大小调整为包含指定位数。For example, numBytes = n/8 + (n % 8 == 0 ?0 : 1),其中 n 是位数。

位不同[(M)]

BYTES

io.debezium.data.Bits

length schema 参数包含一个代表位数(2^31 - 1,如果没有为列提供长度)的整数。生成的 byte[] 包含位(以 little-endian 格式),并根据内容的大小调整。指定的大小 (M) 存储在 io.debezium.data.Bits 类型的 length 参数中。

SMALLINT,SMALLSERIAL

INT16

不适用

整数,SERIAL

INT32

不适用

BIGINT,BIGSERIAL,OID

INT64

不适用

REAL

FLOAT32

不适用

双精度

FLOAT64

不适用

CHAR[(M)]

字符串

不适用

VARCHAR[(M)]

字符串

不适用

CHARACTER[(M)]

字符串

不适用

CHARACTER VARYING[(M)]

字符串

不适用

TIMESTAMPTZ ,带有时区的时间戳

字符串

io.debezium.time.ZonedTimestamp

使用时区信息的时间戳的字符串表示,其中时区为 GMT。

TIMETZ ,带有时区的时间

字符串

io.debezium.time.ZonedTime

带有时区信息的时间值的字符串表示,其中时区为 GMT。

INTERVAL [P]

INT64

io.debezium.time.MicroDuration
(默认)

每月平均的间隔使用 365.25 / 12.0 公式的大约微秒数。

INTERVAL [P]

字符串

io.debezium.time.Interval
(当 interval.handling.mode 设置为 字符串

间隔值的字符串表示,其格式为 P<years>Y<months>M<days>DT<hours>H<minutes>M<seconds>S,例如 P1Y2MDT4H5M6.78S

BYTEA

BYTESSTRING

N/A

根据连接器 的二进制处理模式 设置,即 base64 编码的字符串或 base64-url-safe-encoded 字符串或十六进制编码的字符串。

Debezium 只支持值 hex 的 Postgres 字节a_output 配置。有关 PostgreSQL 二进制数据类型的更多信息,请参阅 PostgreSQL 文档

JSON、JSONB

字符串

io.debezium.data.Json

包含 JSON 文档、数组或 scalar 的字符串表示。

XML

字符串

io.debezium.data.Xml

包含 XML 文档的字符串表示。

UUID

字符串

io.debezium.data.Uuid

包含 PostgreSQL UUID 值的字符串表示。

STRUCT

io.debezium.data.geometry.Point

包含含有两个 FLOAT64 字段 (x,y) 的结构。每个字段代表地理位置的协调。

LTREE

字符串

io.debezium.data.Ltree

包含 PostgreSQL LTREE 值的字符串表示。

CITEXT

字符串

不适用

INET

字符串

不适用

INT4RANGE

字符串

N/A

范围整数。

INT8RANGE

字符串

N/A

Range of bigint.

NUMRANGE

字符串

N/A

范围为.

TSRANGE

字符串

N/A

包含没有时区的时间戳范围的字符串。

TSTZRANGE

字符串

N/A

包含带有本地系统时区的时间戳范围的字符串。

DATERANGE

字符串

N/A

包含日期范围的字符串表示。它始终具有专用的上限。

ENUM

字符串

io.debezium.data.Enum

包含 PostgreSQL ENUM 值的字符串表示。允许的值集合在 allowed schema 参数中维护。

临时类型

除 PostgreSQL 的 TIMESTAMPTZTIMETZ 数据类型之外,它包含时区信息,如何映射 temporal 类型取决于 time.precision.mode 连接器配置属性的值。以下小节描述了这些映射:

time.precision.mode=adaptive

time.precision.mode 属性设置为 adaptive 时,默认连接器根据列的数据类型定义决定字面类型和语义类型。这样可确保事件 完全 表示数据库中的值。

表 7.13. time.precision.mode 被适应 的映射

PostgreSQL 数据类型字面类型(架构类型)语义类型(架构名称)和备注

DATE

INT32

io.debezium.time.Date

代表自 epoch 以来的天数。

TIME (1 ), TIME (2), TIME (3)

INT32

io.debezium.time.Time

代表过去几周的毫秒数,不包括时区信息。

TIME (4) , TIME (5), TIME (6)

INT64

io.debezium.time.MicroTime

代表过去几周的微秒数,不包括时区信息。

TIMESTAMP (1 ), TIMESTAMP (2), TIMESTAMP (3)

INT64

io.debezium.time.Timestamp

代表自 epoch 以来的毫秒数,不包含时区信息。

TIMESTAMP (4), TIMESTAMP (5), TIMESTAMP (6), TIMESTAMP

INT64

io.debezium.time.MicroTimestamp

从 epoch 开始代表微秒的数量,不包括时区信息。

time.precision.mode=adaptive_time_microseconds

time.precision.mode 配置属性被设置为 adaptive_time_microseconds 时,连接器根据列的数据类型定义决定 temporal 类型的字面类型和语义类型。这样可确保事件 精确 表示数据库中的值,但所有 TIME 字段都被捕获为微秒。

表 7.14. time.precision.modeadaptive_time_microseconds时的映射

PostgreSQL 数据类型字面类型(架构类型)语义类型(架构名称)和备注

DATE

INT32

io.debezium.time.Date

代表自 epoch 以来的天数。

TIME([P])

INT64

io.debezium.time.MicroTime

以微秒为单位代表时间值,不包括时区信息。PostgreSQL 允许精确 P 在 0-6 之间存储最多微秒的精度。

TIMESTAMP (1 ), TIMESTAMP (2), TIMESTAMP (3)

INT64

io.debezium.time.Timestamp

代表超过 epoch 的毫秒数,不包括时区信息。

TIMESTAMP (4) , TIMESTAMP (5), TIMESTAMP (6), TIMESTAMP

INT64

io.debezium.time.MicroTimestamp

代表超过 epoch 的微秒数,不包括时区信息。

time.precision.mode=connect

time.precision.mode 配置属性设为 connect 时,连接器将使用 Kafka Connect 逻辑类型。当消费者只能处理内置的 Kafka Connect 逻辑类型且无法处理变量精度时间值时,这很有用。但是,因为 PostgreSQL 支持微秒精度,因此带有 连接 时间精度模式的连接器 生成的事件会导致 数据库列的 fractional second 精度 值大于 3 时丢失精度。

表 7.15. time.precision.modeconnect时的映射

PostgreSQL 数据类型字面类型(架构类型)语义类型(架构名称)和备注

DATE

INT32

org.apache.kafka.connect.data.Date

代表自 epoch 后的天数。

TIME([P])

INT64

org.apache.kafka.connect.data.Time

从中夜起代表毫秒的数量,不包括时区信息。PostgreSQL 允许 P 在 0-6 范围内存储最多微秒的精度,但此模式在 P 大于 3 时会导致精度丢失。

TIMESTAMP([P])

INT64

org.apache.kafka.connect.data.Timestamp

从 epoch 开始代表毫秒的数量,不包括时区信息。PostgreSQL 允许 P 在 0-6 范围内存储最多微秒的精度,但此模式在 P 大于 3 时会导致精度丢失。

TIMESTAMP 类型

TIMESTAMP 类型代表没有时区信息的时间戳。这些列根据 UTC 转换为等同的 Kafka Connect 值。例如,当 time.precision.mode 没有设置为 connect 时,TIMESTAMP 值 "2018-06-20 15:13:16.945104" 由一个带有值 "1529507596945104" 的 io.debezium.time.MicroTimestamp 代表。

运行 Kafka Connect 和 Debezium 的 JVM 的时区不会影响这个转换。

PostgreSQL 支持在 TIMESTAMP 列中使用 +/-infinite 值。这些特殊的值转换为时间戳,在正无限循环的情况下值为 9223372036825200000,在负无限循环的情况值为 -9223372036832400000。这个行为模拟 PostgreSQL JDBC 驱动程序的标准行为。有关参考,请参阅 org.postgresql.PGStatement 接口。

十进制类型

PostgreSQL 连接器配置属性 decimal.handling.mode 的设置决定了连接器如何映射十进制类型。

当将 decimal.handling.mode 属性设置为 精确 时,连接器为所有 DECIMALNUMERICMONEY 列使用 Kafka Connect org.apache.kafka.connect.data.Decimal 逻辑类型。这是默认的模式。

表 7.16. 当 decimal.handling.mode精确的映射

PostgreSQL 数据类型字面类型(架构类型)语义类型(架构名称)和备注

NUMERIC[(M[,D])]

BYTES

org.apache.kafka.connect.data.Decimal

scale 模式参数包含一个整数,代表十进制点被转换了多少位。

DECIMAL[(M[,D])]

BYTES

org.apache.kafka.connect.data.Decimal

scale 模式参数包含一个整数,代表十进制点被转换了多少位。

MONEY[(M[,D])]

BYTES

org.apache.kafka.connect.data.Decimal

scale 模式参数包含一个整数,代表十进制点被转换了多少位。scale schema 参数由 sales. fraction.digits 连接器配置属性决定。

此规则有一个例外。当在没有扩展限制的情况下使用 NUMERICDECIMAL 类型时,来自数据库的值为每个值具有不同的(variable)扩展。在这种情况下,连接器使用 io.debezium.data.VariableScaleDecimal,其中包含值以及传输值的规模。

表 7.17. 没有缩放限制时 DECIMALNUMERIC 类型的映射

PostgreSQL 数据类型字面类型(架构类型)语义类型(架构名称)和备注

数字

STRUCT

io.debezium.data.VariableScaleDecimal

包含含有两个字段的结构: 扩展 INT32 类型,其中包含传输的值和类型为 BYTES 的值,其中包含未扩展形式的原始值。

十进制

STRUCT

io.debezium.data.VariableScaleDecimal

包含含有两个字段的结构: 扩展 INT32 类型,其中包含传输的值和类型为 BYTES 的值,其中包含未扩展形式的原始值。

当将 decimal.handling.mode 属性设置为 double 时,连接器表示所有 DECIMALNUMERICMONEY 值作为 Java double 值,并将它们编码,如下表所示。

表 7.18. decimal.handling.mode双时的映射

PostgreSQL 数据类型字面类型(架构类型)语义类型(架构名称)

NUMERIC[(M[,D])]

FLOAT64

 

DECIMAL[(M[,D])]

FLOAT64

 

MONEY[(M[,D])]

FLOAT64

 

decimal.handling.mode 配置属性的最后可能设置是 字符串。在这种情况下,连接器代表 DECIMALNUMERICMONEY 值作为其格式的字符串表示,并将它们编码,如下表所示。

表 7.19. 当 decimal.handling.mode字符串时的映射

PostgreSQL 数据类型字面类型(架构类型)语义类型(架构名称)

NUMERIC[(M[,D])]

字符串

 

DECIMAL[(M[,D])]

字符串

 

MONEY[(M[,D])]

字符串

 

PostgreSQL 支持 NaN (不是数字)作为在 decimal.handling.mode 设置为 stringdouble 时存储在 DECIMAL/NUMERIC 值的特殊值。在这种情况下,连接器将 NaN 编码为 Double.NaN 或字符串常量 NAN

HSTORE 类型

PostgreSQL 连接器配置属性 hstore.handling.mode 的设置决定了连接器如何映射 HSTORE 值。

dhstore.handling.mode 属性设置为 json (默认值),连接器表示 HSTORE 值作为 JSON 值的字符串表示,并将它们编码,如下表所示。当 hstore.handling.mode 属性设置为 map 时,连接器将 MAP 模式类型用于 HSTORE 值。

表 7.20. HSTORE 数据类型映射

PostgreSQL 数据类型字面类型(架构类型)语义类型(架构名称)和备注

HSTORE

字符串

io.debezium.data.Json

Example: 使用 JSON converter 的输出表示是 {"key" : "val"}

HSTORE

MAP

N/A

Example: 使用 JSON converter 的输出表示是 {"key" : "val"}

域类型

PostgreSQL 支持基于其他底层类型的用户定义的类型。当使用此类列类型时,Debezium 会根据完整类型层次结构公开列的表示。

重要

捕获使用 PostgreSQL 域类型的列中的更改需要特殊考虑。当将列定义为扩展其中一个默认数据库类型的域类型,并且 domain 类型定义了自定义长度或缩放时,生成的架构继承了定义长度或缩放。

当将列定义为一个域类型来扩展定义自定义长度或缩放的另一个域类型时,生成的架构 不会继承 定义的长度或缩放,因为 PostgreSQL 驱动程序列元数据中没有这些信息。

网络地址类型

PostgreSQL 具有可存储 IPv4、IPv6 和 MAC 地址的数据类型。最好使用这些类型而不是纯文本类型来存储网络地址。网络地址类型提供输入错误检查以及特殊的运算符和功能。

表 7.21. 网络地址类型的映射

PostgreSQL 数据类型字面类型(架构类型)语义类型(架构名称)和备注

INET

字符串

N/A

IPv4 和 IPv6 网络

CIDR

字符串

N/A

IPv4 和 IPv6 主机和网络

MACADDR

字符串

N/A

MAC 地址

MACADDR8

字符串

N/A

MAC 地址,格式为 EUI-64

PostGIS 类型

PostgreSQL 连接器支持所有 PostGIS 数据类型

表 7.22. PostGIS 数据类型映射

PostGIS 数据类型字面类型(架构类型)语义类型(架构名称)和备注

GEOMETRY
(计划)

STRUCT

io.debezium.data.geometry.Geometry

包含带有两个字段的结构:

  • Srid (INT32) - Spatial Reference System Identifier,用于定义哪些 geometry 对象存储在结构中。
  • Wkb (BYTES) - 以 Well-Known-Binary 格式编码的 geometry 对象的二进制表示。

有关格式详情,请参阅 Open Geospatial Consortium Simple features Access 规格

GEOGRAPHY
(spherical)

STRUCT

io.debezium.data.geometry.Geography

包含带有两个字段的结构:

  • Srid (INT32) - Spatial Reference System Identifier,用于定义哪些阻塞对象类型存储在结构中。
  • Wkb (BYTES) - 以 Well-Known-Binary 格式编码的 geometry 对象的二进制表示。

有关格式详情,请参阅 Open Geospatial Consortium Simple features Access 规格

粘贴的值

PostgreSQL 对页面大小具有硬性限制。这意味着,需要使用 TOAST 存储存储 超过 8 KB 的值。这会影响来自数据库的复制消息。使用 TOAST 机制存储且尚未更改的值不会包含在消息中,除非它们是表的副本身份的一部分。Debezium 无法直接从数据库中读取缺失的值,因为这可能导致竞争条件。因此,Debebe 会遵循这些规则来处理粘贴的值:

  • 带有 REPLICA IDENTITY FULL - TOAST 列值的表是更改事件中的 beforeafter 字段的一部分,就像任何其他列一样。
  • 带有 REPLICA IDENTITY DEFAULT 的表 - 当从数据库接收 UPDATE 事件时,任何没有更改的 TOAST 列值都不会包含在事件中。同样,当收到 DELETE 事件时,在 before 字段中没有 TOAST 列。由于 Debezium 无法安全地提供列值,因此连接器会返回一个占位符值,如连接器配置属性 unavailable.value.placeholder 定义。

默认值

如果为数据库模式中的列指定了默认值,PostgreSQL 连接器将尽可能尝试将这个值传播到 Kafka 模式。最常见的数据类型都被支持,包括:

  • 布尔值
  • 数字类型(INTFLOATNUMERIC 等)
  • 文本类型(CHARVARCHARTEXT 等)
  • temporal 类型(DATE,TIME,INTERVAL,TIMESTAMP,TIMESTAMPTZ)
  • JSONJSONBXML
  • UUID

请注意,对于临时类型,默认值解析由 PostgreSQL 库提供;因此,PostgreSQL 通常支持的任何字符串表示都应被连接器支持。

如果默认值由函数生成,而不是直接指定,则连接器将为给定的数据类型导出等效的 0。这些值包括:

  • FALSE for BOOLEAN
  • 0, 带有适当的精度,对于数字类型
  • 文本/XML 类型的空字符串
  • JSON 类型 {}
  • 1970-01-01 用于 DATE,TIMESTAMP,TIMESTAMPTZ 类型
  • 00:00 代表 TIME
  • E114H for INTERVAL
  • 00000000-0000-0000-0000-000000000000 用于 UUID

这个支持目前只扩展为明确使用功能。例如,CURRENT_TIMESTAMP (6) 支持括号,但 CURRENT_TIMESTAMP 不支持。

重要

在将 PostgreSQL 连接器与强制实施架构版本间兼容性的模式 registry 搭配使用时,对默认值的传播主要存在允许安全模式演进。由于这个主要关注,以及不同插件的刷新行为,Kafka 模式中的默认值无法保证始终与数据库模式中的默认值同步。

  • 默认值可能会在 Kafka 模式中出现 'late',具体取决于给定插件触发对内存模式的刷新。如果默认值在刷新中多次更改,则值不会在 Kafka 模式中显示/跳过
  • 如果在连接器有等待处理的记录时触发了模式刷新,则默认值可能会在 Kafka 模式中出现"early"。这是因为在刷新时从数据库读取列元数据,而不是在复制消息中存在。如果连接器位于后,并且发生刷新,或者在更新继续写入源数据库时停止连接器时启动连接器。

此行为可能是意外的,但仍然是安全的。只有架构定义会受到影响,但消息中存在的实际值与写入源数据库的内容保持一致。