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 数据类型 | 字面类型(架构类型) | 语义类型(架构名称)和备注 |
|---|---|---|
|
|
| 不适用 |
|
|
| 不适用 |
|
|
|
|
|
|
|
|
|
|
| 不适用 |
|
|
| 不适用 |
|
|
| 不适用 |
|
|
| 不适用 |
|
|
| 不适用 |
|
|
| 不适用 |
|
|
| 不适用 |
|
|
| 不适用 |
|
|
| 不适用 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
N/A |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 不适用 |
|
|
| 不适用 |
|
|
|
N/A |
|
|
|
N/A |
|
|
|
N/A |
|
|
|
N/A |
|
|
|
N/A |
|
|
|
N/A |
|
|
|
|
临时类型
除 PostgreSQL 的 TIMESTAMPTZ 和 TIMETZ 数据类型之外,它包含时区信息,如何映射 temporal 类型取决于 time.precision.mode 连接器配置属性的值。以下小节描述了这些映射:
time.precision.mode=adaptive
当 time.precision.mode 属性设置为 adaptive 时,默认连接器根据列的数据类型定义决定字面类型和语义类型。这样可确保事件 完全 表示数据库中的值。
表 7.13. time.precision.mode 被适应 的映射
| PostgreSQL 数据类型 | 字面类型(架构类型) | 语义类型(架构名称)和备注 |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
time.precision.mode=adaptive_time_microseconds
当 time.precision.mode 配置属性被设置为 adaptive_time_microseconds 时,连接器根据列的数据类型定义决定 temporal 类型的字面类型和语义类型。这样可确保事件 精确 表示数据库中的值,但所有 TIME 字段都被捕获为微秒。
表 7.14. time.precision.mode 为 adaptive_time_microseconds时的映射
| PostgreSQL 数据类型 | 字面类型(架构类型) | 语义类型(架构名称)和备注 |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
time.precision.mode=connect
当 time.precision.mode 配置属性设为 connect 时,连接器将使用 Kafka Connect 逻辑类型。当消费者只能处理内置的 Kafka Connect 逻辑类型且无法处理变量精度时间值时,这很有用。但是,因为 PostgreSQL 支持微秒精度,因此带有 连接 时间精度模式的连接器 生成的事件会导致 数据库列的 fractional second 精度 值大于 3 时丢失精度。
表 7.15. time.precision.mode 为 connect时的映射
| PostgreSQL 数据类型 | 字面类型(架构类型) | 语义类型(架构名称)和备注 |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
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 属性设置为 精确 时,连接器为所有 DECIMAL、NUMERIC 和 MONEY 列使用 Kafka Connect org.apache.kafka.connect.data.Decimal 逻辑类型。这是默认的模式。
表 7.16. 当 decimal.handling.mode 是 精确的映射
| PostgreSQL 数据类型 | 字面类型(架构类型) | 语义类型(架构名称)和备注 |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
此规则有一个例外。当在没有扩展限制的情况下使用 NUMERIC 或 DECIMAL 类型时,来自数据库的值为每个值具有不同的(variable)扩展。在这种情况下,连接器使用 io.debezium.data.VariableScaleDecimal,其中包含值以及传输值的规模。
表 7.17. 没有缩放限制时 DECIMAL 和 NUMERIC 类型的映射
| PostgreSQL 数据类型 | 字面类型(架构类型) | 语义类型(架构名称)和备注 |
|---|---|---|
|
|
|
|
|
|
|
|
当将 decimal.handling.mode 属性设置为 double 时,连接器表示所有 DECIMAL、NUMERIC 和 MONEY 值作为 Java double 值,并将它们编码,如下表所示。
表 7.18. decimal.handling.mode 为 双时的映射
| PostgreSQL 数据类型 | 字面类型(架构类型) | 语义类型(架构名称) |
|---|---|---|
|
|
| |
|
|
| |
|
|
|
decimal.handling.mode 配置属性的最后可能设置是 字符串。在这种情况下,连接器代表 DECIMAL、NUMERIC 和 MONEY 值作为其格式的字符串表示,并将它们编码,如下表所示。
表 7.19. 当 decimal.handling.mode 为 字符串时的映射
| PostgreSQL 数据类型 | 字面类型(架构类型) | 语义类型(架构名称) |
|---|---|---|
|
|
| |
|
|
| |
|
|
|
PostgreSQL 支持 NaN (不是数字)作为在 decimal.handling.mode 设置为 string 或 double 时存储在 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 数据类型 | 字面类型(架构类型) | 语义类型(架构名称)和备注 |
|---|---|---|
|
|
|
|
|
|
|
N/A |
域类型
PostgreSQL 支持基于其他底层类型的用户定义的类型。当使用此类列类型时,Debezium 会根据完整类型层次结构公开列的表示。
捕获使用 PostgreSQL 域类型的列中的更改需要特殊考虑。当将列定义为扩展其中一个默认数据库类型的域类型,并且 domain 类型定义了自定义长度或缩放时,生成的架构继承了定义长度或缩放。
当将列定义为一个域类型来扩展定义自定义长度或缩放的另一个域类型时,生成的架构 不会继承 定义的长度或缩放,因为 PostgreSQL 驱动程序列元数据中没有这些信息。
网络地址类型
PostgreSQL 具有可存储 IPv4、IPv6 和 MAC 地址的数据类型。最好使用这些类型而不是纯文本类型来存储网络地址。网络地址类型提供输入错误检查以及特殊的运算符和功能。
表 7.21. 网络地址类型的映射
| PostgreSQL 数据类型 | 字面类型(架构类型) | 语义类型(架构名称)和备注 |
|---|---|---|
|
|
|
N/A |
|
|
|
N/A |
|
|
|
N/A |
|
|
|
N/A |
PostGIS 类型
PostgreSQL 连接器支持所有 PostGIS 数据类型。
表 7.22. PostGIS 数据类型映射
| PostGIS 数据类型 | 字面类型(架构类型) | 语义类型(架构名称)和备注 |
|---|---|---|
|
|
|
有关格式详情,请参阅 Open Geospatial Consortium Simple features Access 规格。 |
|
|
|
有关格式详情,请参阅 Open Geospatial Consortium Simple features Access 规格。 |
粘贴的值
PostgreSQL 对页面大小具有硬性限制。这意味着,需要使用 TOAST 存储存储 超过 8 KB 的值。这会影响来自数据库的复制消息。使用 TOAST 机制存储且尚未更改的值不会包含在消息中,除非它们是表的副本身份的一部分。Debezium 无法直接从数据库中读取缺失的值,因为这可能导致竞争条件。因此,Debebe 会遵循这些规则来处理粘贴的值:
-
带有
REPLICA IDENTITY FULL- TOAST 列值的表是更改事件中的before和after字段的一部分,就像任何其他列一样。 -
带有
REPLICA IDENTITY DEFAULT的表 - 当从数据库接收UPDATE事件时,任何没有更改的 TOAST 列值都不会包含在事件中。同样,当收到DELETE事件时,在before字段中没有 TOAST 列。由于 Debezium 无法安全地提供列值,因此连接器会返回一个占位符值,如连接器配置属性unavailable.value.placeholder定义。
默认值
如果为数据库模式中的列指定了默认值,PostgreSQL 连接器将尽可能尝试将这个值传播到 Kafka 模式。最常见的数据类型都被支持,包括:
-
布尔值 -
数字类型(
INT、FLOAT、NUMERIC等) -
文本类型(
CHAR、VARCHAR、TEXT等) -
temporal 类型(
DATE,TIME,INTERVAL,TIMESTAMP,TIMESTAMPTZ) -
JSON、JSONB、XML -
UUID
请注意,对于临时类型,默认值解析由 PostgreSQL 库提供;因此,PostgreSQL 通常支持的任何字符串表示都应被连接器支持。
如果默认值由函数生成,而不是直接指定,则连接器将为给定的数据类型导出等效的 0。这些值包括:
-
FALSEforBOOLEAN -
0,带有适当的精度,对于数字类型 - 文本/XML 类型的空字符串
-
JSON 类型
{} -
1970-01-01用于DATE,TIMESTAMP,TIMESTAMPTZ类型 -
00:00代表TIME -
E114HforINTERVAL -
00000000-0000-0000-0000-000000000000用于UUID
这个支持目前只扩展为明确使用功能。例如,CURRENT_TIMESTAMP (6) 支持括号,但 CURRENT_TIMESTAMP 不支持。
在将 PostgreSQL 连接器与强制实施架构版本间兼容性的模式 registry 搭配使用时,对默认值的传播主要存在允许安全模式演进。由于这个主要关注,以及不同插件的刷新行为,Kafka 模式中的默认值无法保证始终与数据库模式中的默认值同步。
- 默认值可能会在 Kafka 模式中出现 'late',具体取决于给定插件触发对内存模式的刷新。如果默认值在刷新中多次更改,则值不会在 Kafka 模式中显示/跳过
- 如果在连接器有等待处理的记录时触发了模式刷新,则默认值可能会在 Kafka 模式中出现"early"。这是因为在刷新时从数据库读取列元数据,而不是在复制消息中存在。如果连接器位于后,并且发生刷新,或者在更新继续写入源数据库时停止连接器时启动连接器。
此行为可能是意外的,但仍然是安全的。只有架构定义会受到影响,但消息中存在的实际值与写入源数据库的内容保持一致。