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