6.3. Debezium Oracle 连接器如何映射数据类型

当 Debezium Oracle 连接器检测到表行值的变化时,它会发出一个代表更改事件的更改事件。每个更改事件记录都与原始表相同,事件记录包含每个列值的字段。表列的数据类型决定了连接器在更改事件字段中代表列的值,如以下部分的表所示。

对于表中的每一列,Debebe 会将源数据类型映射到 字面类型,在某些情况下,在对应的事件字段中,一个 语义类型

字面类型
描述如何代表值,使用以下 Kafka Connect 模式类型之一: INT8,INT16,INT32,INT64,FLOAT32,FLOAT64,BOOLEAN,STRING,BYTES, ARRAY, MAP, 和 STRUCT
语义类型
描述 Kafka Connect 模式如何使用字段的名称来捕获字段 的含义

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

对于某些 Oracle 大对象(CLOB、NCLOB 和 BLOB)和数字数据类型,您可以通过更改默认配置属性设置来操作连接器执行类型映射的方式。有关 Debezium 属性如何控制这些数据类型映射的更多信息,请参阅 Binary 和 Character LOB 类型Numeric 类型

有关 Debezium 连接器如何映射 Oracle 数据类型的更多信息,请参阅以下主题:

字符类型

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

表 6.7. Oracle 基本字符类型的映射

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

CHAR[(M)]

字符串

不适用

NCHAR[(M)]

字符串

不适用

NVARCHAR2[(M)]

字符串

不适用

VARCHAR[(M)]

字符串

不适用

VARCHAR2[(M)]

字符串

不适用

二进制和 Character LOB 类型

使用带有 Debezium Oracle 连接器的 BLOBCLOBNCLOB 只是一个技术预览功能。技术预览功能不受红帽产品服务等级协议(SLA)支持,且功能可能并不完整。红帽不推荐在生产环境中使用它们。这些技术预览功能可以使用户提早试用新的功能,并有机会在开发阶段提供反馈意见。有关红帽技术预览功能支持范围的更多信息,请参阅 https://access.redhat.com/support/offerings/techpreview

下表描述了连接器如何映射二进制和字符大型对象(LOB)数据类型。

表 6.8. Oracle 二进制文件和字符 LOB 类型的映射

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

BFILE

不适用

不支持此数据类型

BLOB

BYTES

raw 字节(默认)、base64 编码的字符串或 base64-url-safe-encoded String,或基于 binary.handling.mode 连接器配置设置的十六进制编码字符串。

CLOB

字符串

不适用

LONG

不适用

不支持此数据类型。

长原始

不适用

不支持此数据类型。

NCLOB

字符串

不适用

RAW

不适用

不支持此数据类型。

注意

如果 Oracle 在 SQL 语句中明确设置或更改,Oracle 只为 CLOBNCLOBBLOB 数据类型提供列值。因此,更改事件永远不会包含未更改的 CLOBNCLOBBLOB 列的值。相反,它们包含由 connector 属性 unavailable.value.placeholder 定义的占位符。

如果更新 CLOBNCLOBBLOB 列的值,则新值将放置在相应更新更改事件的 after 元素中。before 元素包含不可用的值占位符。

数字类型

下表描述了 Debezium Oracle 连接器如何映射数字类型。

注意

您可以通过更改连接器的 decimal.handling.mode 配置属性的值来修改连接器的 decimal.handling.mode 配置属性、NUMBERNUMERICREAL 数据类型的方法。当属性被设置为其 精确 的默认值时,连接器会将这些 Oracle 数据类型映射到 Kafka Connect org.apache.kafka.connect.data.Decimal 逻辑类型,如表所示。当属性的值设置为 doublestring 时,连接器会对某些 Oracle 数据类型使用备用映射。如需更多信息,请参阅 下表中的 Semantic 类型和备注 列。

表 6.9. Oracle 数字数据类型的映射

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

BINARY_FLOAT

FLOAT32

不适用

BINARY_DOUBLE

FLOAT64

不适用

DECIMAL[(P, S)]

BYTES / INT8 / INT16 / INT32 / INT64

org.apache.kafka.connect.data.Decimal,如果使用 BYTES

Handled,相当于 NUMBER (请注意,对于 DECIMAL,S 默认为 0)。

当将 decimal.handling.mode 属性设置为 double 时,连接器代表 DECIMAL 值作为模式类型 FLOAT64 的 Java double 值。

当将 decimal.handling.mode 属性设置为 字符串 时,连接器表示 DECIMAL 值作为其格式的字符串,格式为 schema 类型 STRING

双精度

STRUCT

io.debezium.data.VariableScaleDecimal

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

FLOAT[(P)]

STRUCT

io.debezium.data.VariableScaleDecimal

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

整数,INT

BYTES

org.apache.kafka.connect.data.Decimal

INTEGER 在 Oracle 中映射到 NUMBER (38,0),因此可以保存大于任何 INT 类型的值

NUMBER[(P[, *])]

STRUCT

io.debezium.data.VariableScaleDecimal

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

当将 decimal.handling.mode 属性设置为 double 时,连接器代表 NUMBER 值,作为 schema 类型 FLOAT64 的 Java double 值。

当将 decimal.handling.mode 属性设置为 string 时,连接器显示 NUMBER 值作为一个有特定格式的字符串(如 schema 类型 STRING)。

NUMBER(P, S <= 0)

INT8 / INT16 / INT32 / INT64

缩放 0 的 NUMBER 列代表整数。负等级表示在 Oracle 中舍入舍入,例如,扩展 -2 会导致舍入数百个。

根据精度和扩展,选择以下匹配 Kafka Connect 整数类型之一:

  • P - S < 3, INT8
  • P - S < 5, INT16
  • P - S < 10, INT32
  • P - S < 19, INT64
  • P - S >= 19, BYTES (org.apache.kafka.connect.data.Decimal)

当将 decimal.handling.mode 属性设置为 double 时,连接器代表 NUMBER 值,作为 schema 类型 FLOAT64 的 Java double 值。

当将 decimal.handling.mode 属性设置为 string 时,连接器显示 NUMBER 值作为一个有特定格式的字符串(如 schema 类型 STRING)。

NUMBER (P, S > 0)

BYTES

org.apache.kafka.connect.data.Decimal

NUMBER[(P, S)]

BYTES / INT8 / INT16 / INT32 / INT64

org.apache.kafka.connect.data.Decimal,如果使用 BYTES

Handled,相当于 NUMBER (请注意,对于 NUMERIC,S 默认为 0)。

当将 decimal.handling.mode 属性设置为 double 时,连接器代表 NUMERIC 值,作为模式类型 FLOAT64 的 Java double 值。

当将 decimal.handling.mode 属性设置为 字符串 时,连接器代表 NUMERIC 值作为其格式的字符串,格式为 schema 类型 STRING

SMALLINT

BYTES

org.apache.kafka.connect.data.Decimal

SMALLINT 在 Oracle 中映射到 NUMBER (38,0),因此可以保存大于任何 INT 类型的值

REAL

STRUCT

io.debezium.data.VariableScaleDecimal

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

当将 decimal.handling.mode 属性设置为 double 时,连接器将 REAL 值表示为 schema 类型 FLOAT64 的 Java double 值。

当将 decimal.handling.mode 属性设置为 字符串 时,连接器表示 REAL 值作为其格式的字符串,格式为 schema 类型 STRING

如上所述,Oracle 允许 NUMBER 类型的负扩展。当数字表示为 Decimal 时,这可能会导致在转换为 Avro 格式时出现问题。十进制 类型包括缩放信息,但 Avro 规格 仅允许缩放的正值。根据所使用的模式 registry,可能会导致 Avro 序列化失败。要避免这个问题,您可以使用 NumberToZeroScaleConverter,其将完全高的数字(P - S >= 19),负扩展为零)转换为 12 月类型。它可以配置如下:

converters=zero_scale
zero_scale.type=io.debezium.connector.oracle.converters.NumberToZeroScaleConverter
zero_scale.decimal.mode=precise

默认情况下,数字转换为 Decimal 类型(zero_scale.decimal.mode=precise),但支持完整的两种类型( 和字符串)。

布尔值类型

Oracle 不提供对 BOOLEAN 数据类型的原生支持。但是,常见的做法是使用具有某些语义的其他数据类型来模拟逻辑 BOOLEAN 数据类型的概念。

要允许您将源列转换为布尔值,Debezium 提供了一个 NumberOneToBooleanConverter 自定义转换器,您可以使用以下方法之一:

  • 将所有 NUMBER (1) 列映射到 BOOLEAN 类型。
  • 使用以逗号分隔的正则表达式列表枚举列子集。
    要使用这种转换,您必须使用 selector 参数设置 转换器 配置属性,如下例所示:

    converters=boolean
    boolean.type=io.debezium.connector.oracle.converters.NumberOneToBooleanConverter
    boolean.selector=.*MYTABLE.FLAG,.*.IS_ARCHIVED

临时类型

除 Oracle INTERVALTIMESTAMP WITH TIME ZONETIMESTAMP WITH LOCAL TIME ZONE 数据类型外,连接器转换时类型取决于 time.precision.mode 配置属性的值。

time.precision.mode 配置属性被设置为 adaptive (默认值),那么连接器根据列的数据类型定义决定 temporal 类型的字面和语义类型,以便事件 完全 表示数据库中的值:

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

DATE

INT64

io.debezium.time.Timestamp

代表自 UNIX epoch 开始的毫秒数,不包含时区信息。

间隔日期[(M)] 为秒

FLOAT64

io.debezium.time.MicroDuration

使用 365.25 / 12.0 公式的间隔的微秒数。

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

字符串表示 遵循模式 P<years>Y<months>M<days>DT<hours>H<minutes>M<seconds>S, 例如,P1Y2M3DT4H5M6.78S

间隔年[(M)] 到月

FLOAT64

io.debezium.time.MicroDuration

使用 365.25 / 12.0 公式的间隔的微秒数。

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

字符串表示 遵循模式 P<years>Y<months>M<days>DT<hours>H<minutes>M<seconds>S, 例如,P1Y2M3DT4H5M6.78S

TIMESTAMP(0 - 3)

INT64

io.debezium.time.Timestamp

代表自 UNIX epoch 开始的毫秒数,不包含时区信息。

TIMESTAMP, TIMESTAMP(4 - 6)

INT64

io.debezium.time.MicroTimestamp

代表自 UNIX epoch 开始的微秒数,不包含时区信息。

TIMESTAMP(7 - 9)

INT64

io.debezium.time.NanoTimestamp

代表自 UNIX epoch 开始的纳秒数,不包含时区信息。

使用时区的时间戳

字符串

io.debezium.time.ZonedTimestamp

一个带有时区信息的时间戳的字符串表示。

带有本地时区的时间戳

字符串

io.debezium.time.ZonedTimestamp

> UTC 中时间戳的字符串表示。

time.precision.mode 配置属性设为 connect 时,连接器会使用预定义的 Kafka Connect 逻辑类型。当消费者只了解内置的 Kafka Connect 逻辑类型且无法处理变量精度时间值时,这非常有用。由于 Oracle 支持的精度级别超过 Kafka Connect 支持中的逻辑类型,如果您设置了 time.precision.mode 来连接,因此当数据库列的 fractional second precision 值大于 3 时,会丢失精度结果:

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

DATE

INT32

org.apache.kafka.connect.data.Date

代表自 UNIX epoch 后的天数。

间隔日期[(M)] 为秒

FLOAT64

io.debezium.time.MicroDuration

使用 365.25 / 12.0 公式的间隔的微秒数。

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

字符串表示 遵循模式 P<years>Y<months>M<days>DT<hours>H<minutes>M<seconds>S, 例如,P1Y2M3DT4H5M6.78S

间隔年[(M)] 到月

FLOAT64

io.debezium.time.MicroDuration

使用 365.25 / 12.0 公式的间隔的微秒数。

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

字符串表示 遵循模式 P<years>Y<months>M<days>DT<hours>H<minutes>M<seconds>S, 例如,P1Y2M3DT4H5M6.78S

TIMESTAMP(0 - 3)

INT64

org.apache.kafka.connect.data.Timestamp

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

TIMESTAMP(4 - 6)

INT64

org.apache.kafka.connect.data.Timestamp

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

TIMESTAMP(7 - 9)

INT64

org.apache.kafka.connect.data.Timestamp

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

使用时区的时间戳

字符串

io.debezium.time.ZonedTimestamp

一个带有时区信息的时间戳的字符串表示。

带有本地时区的时间戳

字符串

io.debezium.time.ZonedTimestamp

> UTC 中时间戳的字符串表示。

ROWID 类型

下表描述了连接器如何映射 ROWID (箭头地址)数据类型。

表 6.10. Oracle ROWID 数据类型的映射

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

ROWID

字符串

不适用

UROWID

不适用

不支持此数据类型

用户定义的类型

Oracle 可让您定义自定义数据类型,以便在内置数据类型不满足您的要求时提供灵活性。有几种用户定义的类型,如对象类型、REF 数据类型、Varray 和 Nested Tables。目前,您不能使用带有任何这些用户定义的类型的 Debezium Oracle 连接器。

Oracle 提供的类型

Oracle 提供基于 SQL 的接口,您可以在内置或 ANSI 支持的类型不足时用来定义新类型。Oracle 提供多种常用的数据类型来满足各种目的,如 AnyXMLSpatial 类型。目前,您不能将 Debezium Oracle 连接器与任何这些数据类型一起使用。

默认值

如果为数据库模式中的列指定了默认值,Oracle 连接器会尝试将这个值传播到对应的 Kafka record 字段的 schema。最常见的数据类型都被支持,包括:

  • 字符类型(CHAR,NCHAR,VARCHAR,VARCHAR2,NVARCHAR,NVARCHAR2)
  • 数字类型(INTEGERNUMERIC 等)
  • 临时类型(DATETIMESTAMPINTERVAL 等)

如果临时类型使用 TO_TIMESTAMPTO_DATE 等函数调用来代表默认值,则连接器将通过进行额外的数据库调用来评估函数来解决默认值。例如,如果 DATE 列定义为默认值 TO_DATE ('2021-01-02', 'YYYY-MM-DD'),则该列的默认值将是自该日期的 UNIX 日期或 18629 起的天数。

如果临时类型使用 SYSDATE 常量来代表默认值,则连接器将根据是否定义为 NOT NULL 还是 NULL 来解决此问题。如果列可为空,则不会设置默认值;但是,如果列不可为空,则默认值将解析为 0(用于 DATETIMESTAMP(n) 数据类型)或 1970-01-01T00:00:00Z (用于 TIMESTAMP WITH TIME ZONETIMESTAMP WITH LOCAL TIME ZONE 数据类型)。默认值类型是数字,除非列是 TIMESTAMP WITH TIME ZONETIMESTAMP WITH LOCAL TIME ZONE,在这种情况下,它作为字符串发出。