Debezium系列之:Debezium2.X之Oracle数据库的Debezium连接器

Debezium系列之:Debezium2.X之Oracle数据库的Debezium连接器

  • 一、概述
  • 二、Oracle 连接器的工作原理
    • 1.快照
    • 2.临时快照
    • 3.增量快照
    • 4.快照窗口
    • 5.触发增量快照
    • 6.临时增量快照additional-condition
    • 7.停止增量快照
    • 8.主题名称
    • 9.架构更改主题
    • 10.事物元数据
    • 11.事件缓冲
    • 12.SCN间隙检测
    • 13.低变化频率偏移管理
  • 三、数据变更事件
    • 1.更改事件键
    • 2.更改事件值
    • 3.创建事件
    • 4.更新事件
    • 5.删除事件
    • 6.截断事件
    • 7.数据类型映射
  • 四、字符类型
    • 1.二进制和字符 LOB 类型
    • 2.数值类型
    • 3.布尔类型
    • 4.时间类型
  • 五、重做日志大小
  • 六、为连接器创建用户
  • 七、故障转移数据库
  • 八、Debezium Oracle 连接器配置
  • 九、添加连接器配置
  • 十、可插拔与不可插拔数据库
  • 十一、连接器属性
    • 1.所需的 Debezium Oracle 连接器配置属性
    • 2.Debezium Oracle 连接器数据库架构历史配置属性
  • 十二、XStreams 支持
    • 1.准备数据库
    • 2.为连接器创建 XStream 用户
    • 3.创建 XStream 出站服务器
    • 4.配置 XStream 适配器
    • 5.获取 Oracle JDBC 驱动程序和 XStream API 文件
    • 6.XStream 连接器属性
  • 十三、Debezium2.X接入Oracle数据库实战详细总结

一、概述

Debezium 的 Oracle 连接器捕获并记录在 Oracle 服务器上的数据库中发生的行级更改,包括在连接器运行时添加的表。可以将连接器配置为针对模式和表的特定子集发出更改事件,或者忽略、屏蔽或截断特定列中的值。

Debezium 通过使用本机 LogMiner 数据库包或XStream API从 Oracle 获取更改事件。虽然该连接器可能适用于各种 Oracle 版本,但只有 Oracle EE 12 和 19 已经过测试。

二、Oracle 连接器的工作原理

要以最佳方式配置和运行 Debezium Oracle 连接器,了解连接器如何执行快照、流式传输更改事件、确定 Kafka 主题名称、使用元数据和实施事件缓冲是很有帮助的。

1.快照

通常,Oracle 服务器上的重做日志配置为不保留数据库的完整历史记录。因此,Debezium Oracle 连接器无法从日志中检索数据库的完整历史记录。为了使连接器能够为数据库的当前状态建立基线,连接器第一次启动时,它会执行数据库的初始一致快照。

可以通过设置连接器配置属性的值来自定义连接器创建快照的方式snapshot.mode。默认情况下,连接器的快照模式设置为initial。

用于创建初始快照的默认连接器工作流
当快照模式设置为默认时,连接器完成以下任务来创建快照:

  1. 确定要捕获的表。
  2. 获取ROW SHARE MODE每个捕获表的锁,以防止在创建快照期间发生结构更改。Debezium 持有锁的时间很短。
  3. 从服务器的重做日志中读取当前系统更改号 (SCN) 位置。
  4. 捕获所有相关表的结构。
  5. 释放步骤 2 中获得的锁。
  6. SELECT * FROM … AS OF SCN 123在步骤 3 ( )中读取的 SCN 位置扫描所有相关的数据库表和模式有效,READ为每一行生成一个事件,然后将事件记录写入特定于表的 Kafka 主题。
  7. 在连接器偏移量中记录快照的成功完成。

快照流程开始后,如果由于连接器故障、重平衡或其他原因导致流程中断,则流程会在连接器重启后重新启动。连接器完成初始快照后,它会从它在步骤 3 中读取的位置继续流式传输,这样它就不会错过任何更新。如果连接器出于任何原因再次停止,在它重新启动后,它会从之前停止的地方恢复流式传输更改。

连接器配置属性的设置

  • always:在每个连接器启动时执行快照。快照完成后,连接器开始为后续数据库更改流式传输事件记录。
  • initial:连接器按照创建初始快照的默认工作流程中所述执行数据库快照。快照完成后,连接器开始为后续数据库更改流式传输事件记录
  • initial_only:连接器执行数据库快照并在流式传输任何更改事件记录之前停止,不允许捕获任何后续更改事件。
  • schema_only:连接器捕获所有相关表的结构,执行默认快照工作流中描述的所有步骤,除了它不创建READ事件来表示连接器启动时的数据集(步骤 6)。
  • schema_only_recovery:设置此选项以恢复丢失或损坏的数据库模式历史主题。重新启动后,连接器运行快照,从源表重建主题。您还可以设置该属性以定期修剪经历意外增长的数据库模式历史主题。

警告:如果在上次关闭连接器后将架构更改提交给数据库,请勿使用此模式执行快照。

2.临时快照

默认情况下,连接器仅在首次启动后运行初始快照操作。在这个初始快照之后,在正常情况下,连接器不会重复快照过程。连接器捕获的任何未来更改事件数据仅通过流处理进入。

但是,在某些情况下,连接器在初始快照期间获取的数据可能会变得陈旧、丢失或不完整。为了提供一种重新捕获表数据的机制,Debezium 包含一个执行临时快照的选项。数据库中的以下更改可能会导致执行临时快照:

  • 修改连接器配置以捕获一组不同的表。
  • Kafka 主题被删除,必须重建。
  • 由于配置错误或其他一些问题而发生数据损坏。

可以通过启动所谓的ad-hoc snapshot为您之前捕获快照的表重新运行快照。Ad hoc 快照需要使用信令表。您可以通过向 Debezium 信号表发送信号请求来启动临时快照。

当您启动现有表的临时快照时,连接器会将内容附加到表中已经存在的主题。如果删除了先前存在的主题,Debezium 可以在启用自动创建主题的情况下自动创建一个主题。

临时快照信号指定要包含在快照中的表。快照可以捕获数据库的全部内容,也可以只捕获数据库中表的一个子集。此外,快照可以捕获数据库中表内容的子集。

execute-snapshot您可以通过向信令表发送消息来指定要捕获的表。将信号类型设置execute-snapshot为incremental,并提供要包含在快照中的表的名称,如下表所述:

execute-snapshot临时信号记录示例

  • type:incremental,指定要运行的快照类型。
    设置类型是可选的。目前,您只能请求incremental快照。
  • data-collections:一个数组,其中包含与要拍摄快照的表的完全限定名称匹配的正则表达式。
    名称的格式与配置选项的格式相同signal.data.collection。
  • additional-condition:一个可选字符串,它根据表的列指定条件,以捕获表内容的子集。
  • surrogate-key:一个可选字符串,指定连接器在快照过程中用作表主键的列名。

触发临时快照
execute-snapshot您可以通过向信令表添加具有信号类型的条目来启动临时快照。连接器处理消息后,开始快照操作。快照过程读取第一个和最后一个主键值,并将这些值用作每个表的起点和终点。根据表中的条目数和配置的块大小,Debezium 将表分成块,并继续为每个块连续快照,一次一个。

目前,execute-snapshot操作类型仅触发增量快照。

3.增量快照

为了提供管理快照的灵活性,Debezium 包括一个补充快照机制,称为增量快照。增量快照依赖 Debezium 机制将信号发送到 Debezium 连接器。增量快照基于DDD-3设计文档。

在增量快照中,Debezium 不是像在初始快照中那样一次捕获数据库的完整状态,而是在一系列可配置的块中分阶段捕获每个表。您可以指定希望快照捕获的表以及每个块的大小。块大小决定了在对数据库执行每次提取操作期间快照收集的行数。增量快照的默认块大小为 1 KB。

随着增量快照的进行,Debezium 使用水印来跟踪其进度,维护它捕获的每个表行的记录。与标准的初始快照过程相比,这种分阶段的数据捕获方法具有以下优势:

  • 您可以在捕获流式数据的同时运行增量快照,而不是将流式传输推迟到快照完成。在整个快照过程中,连接器继续从更改日志中捕获近乎实时的事件,并且两个操作都不会阻塞另一个。
  • 如果增量快照的进度中断,您可以在不丢失任何数据的情况下恢复它。进程恢复后,快照从它停止的位置开始,而不是从头重新捕获表。
  • 您可以随时按需运行增量快照,并根据需要重复该过程以适应数据库更新。例如,您可能会在修改连接器配置以将表添加到其table.include.list属性后重新运行快照。

增量快照过程
当您运行增量快照时,Debezium 按主键对每个表进行排序,然后根据配置的块大小将表拆分为块。一个块一个块地工作,然后它捕获一个块中的每个表行。对于它捕获的每一行,快照都会发出一个READ事件。该事件表示块的快照开始时行的值。

随着快照的进行,其他进程可能会继续访问数据库,从而可能修改表记录。为反映此类更改,INSERT、UPDATE或DELETE操作将照常提交到事务日志。同样,正在进行的 Debezium 流处理会继续检测这些变更事件,并向 Kafka 发出相应的变更事件记录。

Debezium 如何解决具有相同主键的记录之间的冲突

在某些情况下,流处理发出的UPDATE或DELETE事件是乱序接收的。READ也就是说,流处理可能会在快照捕获包含该行事件的块之前发出修改表行的事件。当快照最终READ为该行发出相应的事件时,它的值已经被取代。为了确保以正确的逻辑顺序处理乱序到达的增量快照事件,Debezium 采用缓冲方案来解决冲突。只有在解决快照事件和流式事件之间的冲突后,Debezium 才会向 Kafka 发出事件记录。

4.快照窗口

为了帮助解决迟到READ事件和修改同一表行的流式事件之间的冲突,Debezium 采用了所谓的快照窗口。快照窗口划分了增量快照捕获指定表块数据的时间间隔。在块的快照窗口打开之前,Debezium 遵循其通常的行为并从事务日志直接向下游发送事件到目标 Kafka 主题。但是从特定块的快照打开的那一刻起,直到它关闭,Debezium 执行重复数据删除步骤来解决具有相同主键的事件之间的冲突。

对于每个数据集合,Debezium 发出两种类型的事件,并将它们的记录存储在单个目标 Kafka 主题中。它直接从表中捕获的快照记录作为READ操作发出。同时,随着用户继续更新数据收集中的记录,事务日志也会更新以反映每次提交,Debezium 会针对每次更改发出UPDATE或DELETE操作。

当快照窗口打开并且 Debezium 开始处理快照块时,它会将快照记录传送到内存缓冲区。在快照窗口期间,READ将缓冲区中事件的主键与传入流式事件的主键进行比较。如果没有找到匹配项,流式事件记录将直接发送到 Kafka。如果 Debezium 检测到匹配项,它会丢弃缓冲READ事件,并将流式记录写入目标主题,因为流式事件在逻辑上会取代静态快照事件。块的快照窗口关闭后,缓冲区仅包含READ不存在相关事务日志事件的事件。Debezium 将这些剩余READ事件发送到表的 Kafka 主题。

连接器为每个快照块重复该过程。

警告:
用于 Oracle 的 Debezium 连接器不支持在运行增量快照时更改架构。

5.触发增量快照

目前,启动增量快照的唯一方法是向源数据库上的信号表发送临时快照信号。
您将信号作为 SQLINSERT查询提交到信号表。
Debezium 检测到信号表中的更改后,它会读取信号,并运行请求的快照操作。
您提交的查询指定要包含在快照中的表,并且可以选择指定快照操作的类型。目前,快照操作的唯一有效选项是默认值incremental.
要指定要包含在快照中的表,请提供一个data-collections列出表的数组或用于匹配表的正则表达式数组,例如,
{“data-collections”: [“public.MyFirstTable”, “public.MySecondTable”]}
增量快照信号的数组data-collections没有默认值。如果data-collections数组为空,Debezium 检测到不需要任何操作并且不执行快照。

如果要包含在快照中的表的名称在数据库、模式或表的名称中包含点,要将表添加到数组中data-collections,必须将名称的每个部分用双引号转义. 例如,使用以下格式:publicMy.Table"public".“My.Table”

先决条件

  • 信令已启用。
  • 源数据库上存在信令数据集合。
  • 信令数据收集在属性中指定signal.data.collection。

程序

  1. 发送 SQL 查询以将临时增量快照请求添加到信令表:
INSERT INTO <signalTable> (id, type, data) VALUES ('', '', '{"data-collections": ["",""],"type":"","additional-condition":""}');

例如:

INSERT INTO myschema.debezium_signal (id, type, data) 
values ('ad-hoc-1',   
    'execute-snapshot',  
    '{"data-collections": ["schema1.table1", "schema2.table2"], 
    "type":"incremental"}, 
    "additional-condition":"color=blue"}'); 

命令中的id、type、data 参数的值对应于信令表的字段。

  • myschema.debezium_signal:指定源数据库上信令表的完全限定名称。
  • ad-hoc-1:该id参数指定一个任意字符串,该字符串被指定为id信号请求的标识符。
    使用此字符串可将日志记录消息标识到信令表中的条目。Debezium 不使用这个字符串。相反,在快照期间,Debezium 会生成自己的id字符串作为水印信号。
  • execute-snapshot:该type参数指定信号要触发的操作。
  • data-collections:信号字段的必需组件data,指定表名数组或正则表达式以匹配要包含在快照中的表名。
    该数组列出了通过完全限定名称匹配表的正则表达式,使用与您在配置属性中指定连接器信令表名称相同的格式signal.data.collection。
  • incremental:信号字段的可选type组件data,指定要运行的快照操作的类型。
    目前,唯一有效的选项是默认值incremental.
    如果不指定值,连接器将运行增量快照。
  • additional-condition:一个可选字符串,它根据表的列指定条件,以捕获表内容的子集。有关该additional-condition参数的更多信息

6.临时增量快照additional-condition

如果您希望快照仅包含表中内容的子集,您可以通过将参数附加additional-condition到快照信号来修改信号请求。
典型快照的 SQL 查询采用以下形式:

SELECT * FROM <tableName> ....

通过添加additional-condition参数,您可以将WHERE条件附加到 SQL 查询,如以下示例所示:

SELECT * FROM <tableName> WHERE <additional-condition> ....

以下示例显示了一个 SQL 查询,用于将带有附加条件的临时增量快照请求发送到信令表:

INSERT INTO <signalTable> (id, type, data) VALUES ('', '', '{"data-collections": ["",""],"type":"","additional-condition":""}');

例如,假设您有一个products包含以下列的表:

  • id(首要的关键)
  • color
  • quantity

如果希望表的增量快照products只包含where数据项color=blue,可以使用如下SQL语句触发快照:

INSERT INTO myschema.debezium_signal (id, type, data) VALUES('ad-hoc-1', 'execute-snapshot', '{"data-collections": ["schema1.products"],"type":"incremental", "additional-condition":"color=blue"}');

该additional-condition参数还使您能够传递基于多个列的条件。例如,使用上products一个示例中的表,您可以提交一个查询来触发增量快照,该快照仅包含满足以下条件的那些项目的color=blue和quantity>10数据:

INSERT INTO myschema.debezium_signal (id, type, data) VALUES('ad-hoc-1', 'execute-snapshot', '{"data-collections": ["schema1.products"],"type":"incremental", "additional-condition":"color=blue AND quantity>10"}');

以下示例显示了连接器捕获的增量快照事件的 JSON。

{
    "before":null,
    "after": {
        "pk":"1",
        "value":"New data"
    },
    "source": {
        ...
        "snapshot":"incremental" 
    },
    "op":"r", 
    "ts_ms":"1620393591654",
    "transaction":null
}
  • snapshot:指定要运行的快照操作的类型。
    目前,唯一有效的选项是默认值incremental. 在您提交给信号表的 SQL 查询中
    指定一个值是可选的。 如果不指定值,连接器将运行增量快照。
  • op:指定事件类型。快照事件的值为r,表示一个READ操作。

7.停止增量快照

您还可以通过向源数据库上的表发送信号来停止增量快照。您通过发送 SQL 查询向表提交停止快照信号INSERT。
Debezium 检测到信号表中的更改后,它会读取信号,如果正在进行增量快照操作,则会停止。
您提交的查询指定 的快照操作incremental,以及(可选)要删除的当前运行快照的表。

先决条件

  • 信令已启用。
    • 源数据库上存在信令数据集合。
    • 信令数据收集在属性中指定signal.data.collection。

程序

  1. 发送 SQL 查询以停止对信令表的临时增量快照:
INSERT INTO <signalTable> (id, type, data) values ('', 'stop-snapshot', '{"data-collections": ["",""],"type":"incremental"}');

例如,

INSERT INTO myschema.debezium_signal (id, type, data) 
values ('ad-hoc-1',   
    'stop-snapshot',  
    '{"data-collections": ["schema1.table1", "schema2.table2"], 
    "type":"incremental"}'); 

idsignal 命令中的、type、 和data参数的值对应于信令表的字段。

向信令表发送停止增量快照信号的SQL命令字段说明:

  • myschema.debezium_signal:指定源数据库上信令表的完全限定名称。
  • ad-hoc-1:该id参数指定一个任意字符串,该字符串被指定为id信号请求的标识符。
    使用此字符串可将日志记录消息标识到信令表中的条目。Debezium 不使用这个字符串。
  • stop-snapshot:指定type参数指定信号要触发的操作。
  • data-collections:信号字段的可选组件data,指定表名数组或正则表达式以匹配要从快照中删除的表名。
    该数组列出了通过完全限定名称匹配表的正则表达式,使用与您在配置属性中指定连接器信令表名称相同的格式signal.data.collection。如果省略该data字段的这一部分,信号将停止正在进行的整个增量快照。
  • incremental:data指定要停止的快照操作类型的信号字段的必需组件。
    目前,唯一有效的选项是incremental。
    如果不指定type值,该信号将无法停止增量快照。

8.主题名称

默认情况下,Oracle 连接器将表中发生的所有INSERT、UPDATE和DELETE操作的更改事件写入特定于该表的单个 Apache Kafka 主题。连接器使用以下约定来命名更改事件主题:topicPrefix.schemaName.tableName

以下列表提供了默认名称组件的定义:

  • 主题前缀:topic.prefix连接器配置属性指定的主题前缀。
  • 架构名称:发生操作的架构的名称。
  • 表名:发生操作的表的名称。

如果默认主题名称不符合您的要求,您可以配置自定义主题名称。要配置自定义主题名称,您可以在逻辑主题路由 SMT 中指定正则表达式。

9.架构更改主题

您可以配置 Debezium Oracle 连接器以生成模式更改事件,这些事件描述应用于数据库中捕获的表的结构更改。连接器将架构更改事件写入名为 的 Kafka 主题,其中topicName是在配置属性中指定的命名空间topic.prefix。

每当从新表流式传输数据时,Debezium 都会向该主题发出一条新消息。
连接器发送到架构更改主题的消息包含有效负载,并且(可选)还包含更改事件消息的架构。架构更改事件消息的有效负载包括以下元素:

  • ddl:提供导致架构更改的SQL CREATE、ALTER或DROP语句。
  • databaseName:应用语句的数据库的名称。的值databaseName作为消息键。
  • tableChanges:架构更改后整个表架构的结构化表示。该tableChanges字段包含一个数组,其中包含表中每一列的条目。由于结构化表示以 JSON 或 Avro 格式呈现数据,因此消费者无需先通过 DDL 解析器处理消息即可轻松读取消息。

重要的:
切勿对数据库模式历史主题进行分区。为了使数据库模式历史主题正常运行,它必须维护连接器向其发出的事件记录的一致的全局顺序。
为确保主题不在分区之间拆分,请使用以下方法之一设置主题的分区计数:

  • 如果您手动创建数据库架构历史主题,请指定分区计数1.
  • 如果使用 Apache Kafka broker 自动创建数据库模式历史主题,创建主题时,将Kafkanum.partitions配置选项的值设置为1。

每当 Debezium 从新表中流式传输数据或更改表的结构时,都会向该主题发出一条新消息。

示例:发送到 Oracle 连接器架构更改主题的消息
以下示例显示了 JSON 格式的典型架构更改消息。该消息包含表模式的逻辑表示。

{
  "schema": {
  ...
  },
  "payload": {
    "source": {
      "version": "2.2.1.Final",
      "connector": "oracle",
      "name": "server1",
      "ts_ms": 1588252618953,
      "snapshot": "true",
      "db": "ORCLPDB1",
      "schema": "DEBEZIUM",
      "table": "CUSTOMERS",
      "txId" : null,
      "scn" : "1513734",
      "commit_scn": "1513754",
      "lcr_position" : null,
      "rs_id": "001234.00012345.0124",
      "ssn": 1,
      "redo_thread": 1,
      "user_name": "user"
    },
    "ts_ms": 1588252618953, 
    "databaseName": "ORCLPDB1", 
    "schemaName": "DEBEZIUM", //
    "ddl": "CREATE TABLE \"DEBEZIUM\".\"CUSTOMERS\" \n   (    \"ID\" NUMBER(9,0) NOT NULL ENABLE, \n    \"FIRST_NAME\" VARCHAR2(255), \n    \"LAST_NAME" VARCHAR2(255), \n    \"EMAIL\" VARCHAR2(255), \n     PRIMARY KEY (\"ID\") ENABLE, \n     SUPPLEMENTAL LOG DATA (ALL) COLUMNS\n   ) SEGMENT CREATION IMMEDIATE \n  PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 \n NOCOMPRESS LOGGING\n  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645\n  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1\n  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)\n  TABLESPACE \"USERS\" ", 
    "tableChanges": [ 
      {
        "type": "CREATE", 
        "id": "\"ORCLPDB1\".\"DEBEZIUM\".\"CUSTOMERS\"", 
        "table": { 
          "defaultCharsetName": null,
          "primaryKeyColumnNames": [ 
            "ID"
          ],
          "columns": [ 
            {
              "name": "ID",
              "jdbcType": 2,
              "nativeType": null,
              "typeName": "NUMBER",
              "typeExpression": "NUMBER",
              "charsetName": null,
              "length": 9,
              "scale": 0,
              "position": 1,
              "optional": false,
              "autoIncremented": false,
              "generated": false
            },
            {
              "name": "FIRST_NAME",
              "jdbcType": 12,
              "nativeType": null,
              "typeName": "VARCHAR2",
              "typeExpression": "VARCHAR2",
              "charsetName": null,
              "length": 255,
              "scale": null,
              "position": 2,
              "optional": false,
              "autoIncremented": false,
              "generated": false
            },
            {
              "name": "LAST_NAME",
              "jdbcType": 12,
              "nativeType": null,
              "typeName": "VARCHAR2",
              "typeExpression": "VARCHAR2",
              "charsetName": null,
              "length": 255,
              "scale": null,
              "position": 3,
              "optional": false,
              "autoIncremented": false,
              "generated": false
            },
            {
              "name": "EMAIL",
              "jdbcType": 12,
              "nativeType": null,
              "typeName": "VARCHAR2",
              "typeExpression": "VARCHAR2",
              "charsetName": null,
              "length": 255,
              "scale": null,
              "position": 4,
              "optional": false,
              "autoIncremented": false,
              "generated": false
            }
          ],
          "attributes": [ 
            {
              "customAttribute": "attributeValue"
            }
          ]
        }
      }
    ]
  }
}

发送到模式更改主题的消息中的字段描述:

  • ts_ms:显示连接器处理事件的时间的可选字段。该时间基于运行 Kafka Connect 任务的 JVM 中的系统时钟。
    在源对象中,ts_ms 指示在数据库中进行更改的时间。通过将 payload.source.ts_ms 的值与 payload.ts_ms 的值进行比较,您可以确定源数据库更新和 Debezium 之间的延迟。
  • databaseName schemaName:标识包含更改的数据库和模式。
  • ddl:该字段包含负责架构更改的 DDL。
  • tableChanges:包含由 DDL 命令生成的架构更改的一项或多项的数组。
  • type:描述变化的种类。可以type设置为以下值之一:
    CREATE
    表已创建。
    ALTER
    表格已修改。
    DROP
    表已删除。
  • id:已创建、更改或删除的表的完整标识符。在表重命名的情况下,此标识符是表名的串联。,
  • table:表示应用更改后的表元数据。
  • primaryKeyColumnNames:构成表主键的列列表。
  • columns:已更改表中每一列的元数据。
  • attributes:每个表更改的自定义属性元数据。

在连接器发送到架构更改主题的消息中,消息键是包含架构更改的数据库的名称。在以下示例中,该payload字段包含databaseName键:

{
  "schema": {
    "type": "struct",
    "fields": [
      {
        "type": "string",
        "optional": false,
        "field": "databaseName"
      }
    ],
    "optional": false,
    "name": "io.debezium.connector.oracle.SchemaChangeKey"
  },
  "payload": {
    "databaseName": "ORCLPDB1"
  }
}

10.事物元数据

Debezium 可以生成代表事务元数据边界并丰富数据更改事件消息的事件。

BEGIN数据库事务由包含在和关键字之间的语句块表示END。BEGINDebezium 为每笔交易中的和分隔符生成交易边界事件END。事务边界事件包含以下字段:

  • status:BEGIN或END。
  • id:唯一交易标识符的字符串表示。
  • ts_ms:数据源发生事务边界事件(BEGIN或事件)的时间。END如果数据源未向 Debezium 提供事件时间,则该字段代表 Debezium 处理事件的时间。
  • event_count(对于END事件)事务发出的事件总数。
  • data_collections(对于END事件):data_collection和元素对的数组event_count,指示连接器针对源自数据集合的更改发出的事件数。

以下示例显示了典型的事务边界消息:
示例:Oracle 连接器事务边界事件

{
  "status": "BEGIN",
  "id": "5.6.641",
  "ts_ms": 1486500577125,
  "event_count": null,
  "data_collections": null
}

{
  "status": "END",
  "id": "5.6.641",
  "ts_ms": 1486500577691,
  "event_count": 2,
  "data_collections": [
    {
      "data_collection": "ORCLPDB1.DEBEZIUM.CUSTOMER",
      "event_count": 1
    },
    {
      "data_collection": "ORCLPDB1.DEBEZIUM.ORDER",
      "event_count": 1
    }
  ]
}

除非通过选项覆盖topic.transaction,否则连接器会向主题发出事务事件。.transaction

更改数据事件扩充
启用事务元数据后,数据消息Envelope会增加一个新transaction字段。该字段以字段组合的形式提供有关每个事件的信息:
id:唯一交易标识符的字符串表示。
total_order:该事件在交易产生的所有事件中的绝对位置。
data_collection_order:事件在事务发出的所有事件中的每个数据收集位置。

以下示例显示了典型的事务事件消息:

{
  "before": null,
  "after": {
    "pk": "2",
    "aa": "1"
  },
  "source": {
...
  },
  "op": "c",
  "ts_ms": "1580390884335",
  "transaction": {
    "id": "5.6.641",
    "total_order": "1",
    "data_collection_order": "1"
  }
}

11.事件缓冲

Oracle 按照它们发生的顺序将所有更改写入重做日志,包括后来被回滚丢弃的更改。因此,来自不同事务的并发更改交织在一起。当连接器第一次读取更改流时,由于它无法立即确定哪些更改已提交或回滚,因此它会将更改事件临时存储在内部缓冲区中。提交更改后,连接器将更改事件从缓冲区写入 Kafka。连接器会丢弃被回滚丢弃的更改事件。

您可以通过设置属性来配置连接器使用的缓冲机制log.mining.buffer.type。


默认缓冲区类型使用memory. 在默认memory设置下,连接器使用 JVM 进程的堆内存来分配和管理缓冲的事件记录。如果使用memory缓冲区设置,请确保分配给 Java 进程的内存量可以容纳环境中长时间运行的大型事务。

无穷大
Debezium Oracle 连接器还可以配置为使用 Infinispan 作为其缓存提供程序,以嵌入式模式在本地或远程服务器集群上支持缓存存储。为了使用 Infinispan,log.mining.buffer.type必须使用 或 进行infinispan_embedded配置infinispan_remote。

为了允许 Infinispan 缓存配置的灵活性,连接器期望在使用 Infinispan 缓冲事件数据时提供一系列缓存配置属性。查看命名空间中的配置属性log.mining.buffer.infinispan.cache。这些配置属性的内容取决于连接器是与远程 Infinispan 集群集成还是使用嵌入式引擎。

例如,下图说明了在嵌入式模式下使用 Infinispan 时,事务缓存属性的嵌入式配置是什么样的:

<local-cache name="transactions">
  <persistence passivation="false">
    <file-store read-only="false" preload="true" shared="false">
      <data path="./data"/>
      <index path="./index"/>
    file-store>
  persistence>
local-cache>

深入查看配置,缓存配置为持久化。如果事务正在进行中,所有缓存都应以这种方式配置,以避免在连接器重新启动时丢失事务事件。此外,保存缓存的位置由属性定义path,这应该是一个共享位置,可访问所有可能的运行时环境。

另一个示例,下图说明了使用 Infinispan 集群配置的相同缓存:

<distributed-cache name="transactions" statistics="true">
  <encoding media-type="application/x-protostream" />
  <persistence passivation="false">
   <file-store read-only="false" preload="true" shared="false">
     <data path="./data"/>
     <index path="./index"/>
   file-store>
  persistence>
distributed-cache>

就像前面示例中的嵌入式本地缓存配置一样,此配置也被定义为持久的。如果事务正在进行中,所有缓存都应以这种方式配置,以避免在连接器重新启动时丢失事务事件。
但是,与注意有一些区别。首先,缓存被定义为分布式缓存而不是本地缓存。其次,缓存被定义为使用application/x-protostream所有 Debezium 缓存都需要的编码。最后,path文件存储定义不需要任何属性,因为 Infinispan 集群会自动处理它。

重要的:
Infinispan 缓冲区类型被认为是孵化的;缓存格式可能会在版本之间发生变化,并且可能需要重新快照。迁移说明将指出是否需要这样做。
此外,在删除使用 Infinispan 缓冲区的 Debezium Oracle 连接器时,持久缓存文件不会自动从磁盘中删除。如果新连接器部署将使用相同的缓冲区位置,则应在部署新连接器之前手动删除这些文件。

Infinispan Hotrod 客户端集成
Debezium Oracle 连接器利用 Hotrod 客户端与 Infinispan 集群进行通信。任何带有前缀的连接器属性log.mining.buffer.infinispan.client.都将使用命名空间直接传递给 Hotrod 客户端infinispan.client.,从而允许完全自定义客户端与集群交互的方式。

使用此 Infinspan 模式时,至少必须提供一个必需的配置属性:
log.mining.buffer.infinispan.client.hotrod.server_list
使用格式指定 Infinispan 服务器主机名和端口组合的列表:。

12.SCN间隙检测

当 Debezium Oracle 连接器配置为使用 LogMiner 时,它会使用基于系统更改编号 (SCN) 的开始和结束范围从 Oracle 收集更改事件。连接器会自动管理此范围,增加或减少范围取决于连接器是否能够近乎实时地流式传输更改,或者是否必须处理由于数据库中的大量事务或批量事务而积压的更改。

在某些情况下,Oracle 数据库将 SCN 提高异常高的数量,而不是以恒定速率增加 SCN 值。由于特定集成与数据库交互的方式,或者作为热备份等事件的结果,可能会发生 SCN 值的这种跳跃。

Debezium Oracle 连接器依赖于以下配置属性来检测 SCN 差距并调整挖掘范围。
log.mining.scn.gap.detection.gap.size.min
指定最小间隙大小。

log.mining.scn.gap.detection.time.interval.max.ms
指定最大时间间隔。

连接器首先比较当前SCN和当前挖矿范围内最高SCN的变化次数的差异。如果当前 SCN 值与最高 SCN 值之间的差异大于最小间隙大小,则连接器可能检测到 SCN 间隙。为了确认是否存在间隙,连接器接下来将当前 SCN 的时间戳与先前挖掘范围末尾的 SCN 的时间戳进行比较。如果时间戳之间的差异小于最大时间间隔,则确认存在 SCN 间隙。

当出现 SCN 间隙时,Debezium 连接器会自动使用当前 SCN 作为当前挖矿会话范围的终点。这允许连接器快速赶上实时事件,而无需在两者之间挖掘更小的范围,因为 SCN 值增加了一个意想不到的大数字,所以不会返回任何更改。当连接器执行上述步骤以响应 SCN 间隙时,它会忽略log.mining.batch.size.max属性指定的值。在连接器完成挖掘会话并恢复实时事件后,它会恢复执行最大日志挖掘批处理大小。

警告:
只有在连接器运行和处理近乎实时的事件时出现大的 SCN 增量时,SCN 间隙检测才可用。

13.低变化频率偏移管理

Debezium Oracle 连接器跟踪连接器偏移中的系统更改编号,以便在重新启动连接器时,它可以从停止的地方开始。这些偏移量是每个发出的更改事件的一部分;但是,当数据库更改频率较低(每隔几小时或几天)时,如果系统更改编号在事务日志中不再可用,则偏移量可能会变得陈旧并阻止连接器成功重启。

对于使用非 CDB 模式连接到 Oracle 的连接器,您可以启用heartbeat.interval.ms以强制连接器定期发出心跳事件,以便偏移量保持同步。

对于使用 CDB 模式连接 Oracle 的连接器,保持同步比较复杂。不仅要设置heartbeat.interval.ms,还要设置heartbeat.action.query。需要指定这两个属性,因为在 CDB 模式下,连接器仅专门跟踪 PDB 内部的更改。需要一种补充机制来从可插入数据库中触发更改事件。每隔一段时间,心跳操作查询会导致连接器插入一个新的表行,或更新可插入数据库中的现有行。Debezium 检测表更改并为它们发出更改事件,确保偏移量保持同步,即使在不经常处理更改的可插拔数据库中也是如此。

笔记:
要让连接器使用heartbeat.action.query不属于连接器用户帐户的表,您必须授予连接器用户权限以在这些表上运行必要的INSERT或UPDATE查询。

三、数据变更事件

Oracle 连接器发出的每个数据更改事件都有一个键和一个值。键和值的结构取决于更改事件源自的表。

警告:
Debezium Oracle 连接器确保所有 Kafka Connect模式名称都是有效的 Avro 模式名称。这意味着逻辑服务器名称必须以字母字符或下划线 ([az,AZ,_]) 开头,逻辑服务器名称中的其余字符以及架构和表名称中的所有字符都必须是字母数字字符或下划线([az,AZ,0-9,_])。连接器会自动将无效字符替换为下划线字符。
当多个逻辑服务器名称、模式名称或表名称之间的唯一区分字符不是有效字符并且这些字符被下划线替换时,可能会导致意外的命名冲突。

Debezium 和 Kafka Connect 是围绕连续的事件消息流设计的。但是,这些事件的结构可能会随着时间的推移而发生变化,这对于主题消费者来说可能很难处理。为了便于处理可变事件结构,Kafka Connect 中的每个事件都是独立的。每个消息键和值都有两部分:模式和有效负载。模式描述有效载荷的结构,而有效载荷包含实际数据。

1.更改事件键

对于每个更改的表,更改事件键的结构使得在创建事件时表的主键(或唯一键约束)中的每一列都存在一个字段。
例如,customers可能具有以下更改事件键:

CREATE TABLE customers (
  id NUMBER(9) GENERATED BY DEFAULT ON NULL AS IDENTITY (START WITH 1001) NOT NULL PRIMARY KEY,
  first_name VARCHAR2(255) NOT NULL,
  last_name VARCHAR2(255) NOT NULL,
  email VARCHAR2(255) NOT NULL UNIQUE
);

如果配置属性.transaction的值设置为server1,则数据库表customers中发生的每个更改事件的 JSON 表示具有以下关键结构:

{
    "schema": {
        "type": "struct",
        "fields": [
            {
                "type": "int32",
                "optional": false,
                "field": "ID"
            }
        ],
        "optional": false,
        "name": "server1.INVENTORY.CUSTOMERS.Key"
    },
    "payload": {
        "ID": 1004
    }
}

2.更改事件值

更改事件消息中值的结构反映了消息中更改事件中消息键的结构,并且包含模式部分和有效负载部分。
更改事件值的负载
更改事件值的有效负载部分中的信封结构包含以下字段:
op
包含描述操作类型的字符串值的必填字段。Oracle 连接器更改事件值的负载中的字段op包含以下值之一:(c创建或插入)、u(更新)、d(删除)或r(读取,表示快照)。
before
可选字段,如果存在,则描述事件发生前行的状态。该结构由 Kafka Connect 架构描述server1.INVENTORY.CUSTOMERS.Value,server1连接器将其用于表中的所有行inventory.customers。
after
一个可选字段,如果存在,则包含发生更改后行的状态。server1.INVENTORY.CUSTOMERS.Value该结构由用于该字段的相同 Kafka Connect 模式描述before。

source
包含描述事件源元数据结构的必填字段。对于 Oracle 连接器,该结构包括以下字段:

  • Debezium 版本。
  • 连接器名称。
  • 事件是否是正在进行的快照的一部分。
  • 交易 ID(不包括快照)。
  • 更改的 SCN。
  • 指示源数据库中记录更改时间的时间戳(对于快照,时间戳指示快照发生的时间)。
  • 进行更改的用户名

提示:
该commit_scn字段是可选的,它描述了更改事件参与其中的事务提交的 SCN。该字段仅在使用 LogMiner 连接适配器时出现。

该user_name字段仅在使用 LogMiner 连接适配器时填充。

ts_ms
一个可选字段,如果存在,则包含连接器处理事件的时间(基于运行 Kafka Connect 任务的 JVM 中的系统时钟)。

更改事件值的架构
事件消息值的架构部分包含一个架构,该架构描述有效负载的信封结构和其中的嵌套字段。

3.创建事件

以下示例显示了更改事件键示例中描述的表中创建事件值的值:customers

展示完整的JSON结构

{
    "schema":{
        "type":"struct",
        "fields":Array[5],
        "optional":false,
        "name":"server1.DEBEZIUM.CUSTOMERS.Envelope"
    },
    "payload":{
        "before":null,
        "after":Object{...},
        "source":Object{...},
        "op":"c",
        "ts_ms":1532592105975
    }
}
{
    "schema": {
        "type": "struct",
        "fields": [
            {
                "type": "struct",
                "fields": [
                    {
                        "type": "int32",
                        "optional": false,
                        "field": "ID"
                    },
                    {
                        "type": "string",
                        "optional": false,
                        "field": "FIRST_NAME"
                    },
                    {
                        "type": "string",
                        "optional": false,
                        "field": "LAST_NAME"
                    },
                    {
                        "type": "string",
                        "optional": false,
                        "field": "EMAIL"
                    }
                ],
                "optional": true,
                "name": "server1.DEBEZIUM.CUSTOMERS.Value",
                "field": "before"
            },
            {
                "type": "struct",
                "fields": [
                    {
                        "type": "int32",
                        "optional": false,
                        "field": "ID"
                    },
                    {
                        "type": "string",
                        "optional": false,
                        "field": "FIRST_NAME"
                    },
                    {
                        "type": "string",
                        "optional": false,
                        "field": "LAST_NAME"
                    },
                    {
                        "type": "string",
                        "optional": false,
                        "field": "EMAIL"
                    }
                ],
                "optional": true,
                "name": "server1.DEBEZIUM.CUSTOMERS.Value",
                "field": "after"
            },
            {
                "type": "struct",
                "fields": [
                    {
                        "type": "string",
                        "optional": true,
                        "field": "version"
                    },
                    {
                        "type": "string",
                        "optional": false,
                        "field": "name"
                    },
                    {
                        "type": "int64",
                        "optional": true,
                        "field": "ts_ms"
                    },
                    {
                        "type": "string",
                        "optional": true,
                        "field": "txId"
                    },
                    {
                        "type": "string",
                        "optional": true,
                        "field": "scn"
                    },
                    {
                        "type": "string",
                        "optional": true,
                        "field": "commit_scn"
                    },
                    {
                        "type": "string",
                        "optional": true,
                        "field": "rs_id"
                    },
                    {
                        "type": "int64",
                        "optional": true,
                        "field": "ssn"
                    },
                    {
                        "type": "int32",
                        "optional": true,
                        "field": "redo_thread"
                    },
                    {
                        "type": "string",
                        "optional": true,
                        "field": "user_name"
                    },
                    {
                        "type": "boolean",
                        "optional": true,
                        "field": "snapshot"
                    }
                ],
                "optional": false,
                "name": "io.debezium.connector.oracle.Source",
                "field": "source"
            },
            {
                "type": "string",
                "optional": false,
                "field": "op"
            },
            {
                "type": "int64",
                "optional": true,
                "field": "ts_ms"
            }
        ],
        "optional": false,
        "name": "server1.DEBEZIUM.CUSTOMERS.Envelope"
    },
    "payload": {
        "before": null,
        "after": {
            "ID": 1004,
            "FIRST_NAME": "Anne",
            "LAST_NAME": "Kretchmar",
            "EMAIL": "[email protected]"
        },
        "source": {
            "version": "2.2.1.Final",
            "name": "server1",
            "ts_ms": 1520085154000,
            "txId": "6.28.807",
            "scn": "2122185",
            "commit_scn": "2122185",
            "rs_id": "001234.00012345.0124",
            "ssn": 1,
            "redo_thread": 1,
            "user_name": "user",
            "snapshot": false
        },
        "op": "c",
        "ts_ms": 1532592105975
    }
}
 "schema":{
        "type":"struct",
        "fields":[
            {
                "type":"struct",
                "fields":Array[4],
                "optional":true,
                "name":"server1.DEBEZIUM.CUSTOMERS.Value",
                "field":"before"
            },
            {
                "type":"struct",
                "fields":Array[4],
                "optional":true,
                "name":"server1.DEBEZIUM.CUSTOMERS.Value",
                "field":"after"
            },
            {
                "type":"struct",
                "fields":Array[11],
                "optional":false,
                "name":"io.debezium.connector.oracle.Source",
                "field":"source"
            },
            {
                "type":"string",
                "optional":false,
                "field":"op"
            },
            {
                "type":"int64",
                "optional":true,
                "field":"ts_ms"
            }
        ],
        "optional":false,
        "name":"server1.DEBEZIUM.CUSTOMERS.Envelope"
    }
    "schema":{
        "type":"struct",
        "fields":[
            {
                "type":"struct",
                "fields":[
                    {
                        "type":"int32",
                        "optional":false,
                        "field":"ID"
                    },
                    {
                        "type":"string",
                        "optional":false,
                        "field":"FIRST_NAME"
                    },
                    {
                        "type":"string",
                        "optional":false,
                        "field":"LAST_NAME"
                    },
                    {
                        "type":"string",
                        "optional":false,
                        "field":"EMAIL"
                    }
                ],
                "optional":true,
                "name":"server1.DEBEZIUM.CUSTOMERS.Value",
                "field":"before"
            },
            {
                "type":"struct",
                "fields":[
                    {
                        "type":"int32",
                        "optional":false,
                        "field":"ID"
                    },
                    {
                        "type":"string",
                        "optional":false,
                        "field":"FIRST_NAME"
                    },
                    {
                        "type":"string",
                        "optional":false,
                        "field":"LAST_NAME"
                    },
                    {
                        "type":"string",
                        "optional":false,
                        "field":"EMAIL"
                    }
                ],
                "optional":true,
                "name":"server1.DEBEZIUM.CUSTOMERS.Value",
                "field":"after"
            },
            {
                "type":"struct",
                "fields":[
                    {
                        "type":"string",
                        "optional":true,
                        "field":"version"
                    },
                    {
                        "type":"string",
                        "optional":false,
                        "field":"name"
                    },
                    {
                        "type":"int64",
                        "optional":true,
                        "field":"ts_ms"
                    },
                    {
                        "type":"string",
                        "optional":true,
                        "field":"txId"
                    },
                    {
                        "type":"string",
                        "optional":true,
                        "field":"scn"
                    },
                    {
                        "type":"string",
                        "optional":true,
                        "field":"commit_scn"
                    },
                    {
                        "type":"string",
                        "optional":true,
                        "field":"rs_id"
                    },
                    {
                        "type":"int64",
                        "optional":true,
                        "field":"ssn"
                    },
                    {
                        "type":"int32",
                        "optional":true,
                        "field":"redo_thread"
                    },
                    {
                        "type":"string",
                        "optional":true,
                        "field":"user_name"
                    },
                    {
                        "type":"boolean",
                        "optional":true,
                        "field":"snapshot"
                    }
                ],
                "optional":false,
                "name":"io.debezium.connector.oracle.Source",
                "field":"source"
            },
            {
                "type":"string",
                "optional":false,
                "field":"op"
            },
            {
                "type":"int64",
                "optional":true,
                "field":"ts_ms"
            }
        ],
        "optional":false,
        "name":"server1.DEBEZIUM.CUSTOMERS.Envelope"
    }
    "payload":{
        "before":null,
        "after":{
            "ID":1004,
            "FIRST_NAME":"Anne",
            "LAST_NAME":"Kretchmar",
            "EMAIL":"[email protected]"
        },
        "source":{
            "version":"2.2.1.Final",
            "name":"server1",
            "ts_ms":1520085154000,
            "txId":"6.28.807",
            "scn":"2122185",
            "commit_scn":"2122185",
            "rs_id":"001234.00012345.0124",
            "ssn":1,
            "redo_thread":1,
            "user_name":"user",
            "snapshot":false
        },
        "op":"c",
        "ts_ms":1532592105975
    }

4.更新事件

以下示例显示连接器从与前面的创建事件相同的表中捕获的更新更改事件。

{
    "schema": { ... },
    "payload": {
        "before": {
            "ID": 1004,
            "FIRST_NAME": "Anne",
            "LAST_NAME": "Kretchmar",
            "EMAIL": "[email protected]"
        },
        "after": {
            "ID": 1004,
            "FIRST_NAME": "Anne",
            "LAST_NAME": "Kretchmar",
            "EMAIL": "[email protected]"
        },
        "source": {
            "version": "2.2.1.Final",
            "name": "server1",
            "ts_ms": 1520085811000,
            "txId": "6.9.809",
            "scn": "2125544",
            "commit_scn": "2125544",
            "rs_id": "001234.00012345.0124",
            "ssn": 1,
            "redo_thread": 1,
            "user_name": "user",
            "snapshot": false
        },
        "op": "u",
        "ts_ms": 1532592713485
    }
}

有效负载与创建(插入)事件的有效负载具有相同的结构,但以下值不同:

  • op该字段的值为u,表示此行因更新而更改。
  • 该before字段显示具有数据库提交之前存在的值的行的先前状态update。
  • 该after字段显示行的更新状态,值EMAIL现在设置为[email protected]
  • 该source字段的结构包括与以前相同的字段,但值不同,因为连接器从重做日志中的不同位置捕获了事件。
  • 该ts_ms字段显示指示 Debezium 何时处理事件的时间戳。

注意:
更新行的主键/唯一键的列时,行键的值会更改。因此,Debezium在此类更新后发出三个事件:

  • 一个DELETE事件。
  • 具有该行的旧键的逻辑删除事件。
  • INSERT为行提供新键的事件。

5.删除事件

以下示例显示了前面创建和更新事件示例中显示的表的删除事件。删除事件的部分与那些事件的部分相同。

{
    "schema": { ... },
    "payload": {
        "before": {
            "ID": 1004,
            "FIRST_NAME": "Anne",
            "LAST_NAME": "Kretchmar",
            "EMAIL": "[email protected]"
        },
        "after": null,
        "source": {
            "version": "2.2.1.Final",
            "name": "server1",
            "ts_ms": 1520085153000,
            "txId": "6.28.807",
            "scn": "2122184",
            "commit_scn": "2122184",
            "rs_id": "001234.00012345.0124",
            "ssn": 1,
            "redo_thread": 1,
            "user_name": "user",
            "snapshot": false
        },
        "op": "d",
        "ts_ms": 1532592105960
    }
}

与create或updatepayload事件的负载相比,事件的这一部分揭示了几个差异:

  • op该字段的值为d,表示该行已被删除。
  • 该before字段显示随数据库提交删除的行的先前状态。
  • after该字段的值为null,表示该行不再存在。
  • 该字段的结构包括许多存在于创建或更新source事件中的键,但、ts_ms、scn和txId字段中的值是不同的。
  • 显示ts_ms一个时间戳,指示 Debezium 何时处理此事件。

6.截断事件

截断 更改事件表示表已被截断。消息键null在这种情况下,消息值如下所示:

{
    "schema": { ... },
    "payload": {
        "before": null,
        "after": null,
        "source": { 
            "version": "2.2.1.Final",
            "connector": "oracle",
            "name": "oracle_server",
            "ts_ms": 1638974535000,
            "snapshot": "false",
            "db": "ORCLPDB1",
            "sequence": null,
            "schema": "DEBEZIUM",
            "table": "TEST_TABLE",
            "txId": "02000a0037030000",
            "scn": "13234397",
            "commit_scn": "13271102",
            "lcr_position": null,
            "rs_id": "001234.00012345.0124",
            "ssn": 1,
            "redo_thread": 1,
            "user_name": "user"
        },
        "op": "t", 
        "ts_ms": 1638974558961, 
        "transaction": null
    }
}

source:
描述事件源元数据的必填字段。在截断事件值中,字段结构与同一表的创建、更新和删除source事件相同,提供以下元数据:

  • Debezium 版本
  • 连接器类型和名称
  • 包含新行的数据库和表
  • 架构名称
  • 如果事件是快照的一部分(总是截断false事件)
  • 执行操作的事务 ID
  • 操作的SCN
  • 在数据库中进行更改时的时间戳
  • 执行更改的用户名

op:描述操作类型的强制字符串。字段op值为t,表示此表已被截断。

ts_ms:
显示连接器处理事件的时间的可选字段。该时间基于运行 Kafka Connect 任务的 JVM 中的系统时钟。
在source对象中,ts_ms指示在数据库中进行更改的时间。通过将 的值payload.source.ts_ms与 的值进行比较payload.ts_ms,您可以确定源数据库更新和 Debezium 之间的滞后。

因为truncate事件表示对整个表所做的更改,并且没有消息键,所以在具有多个分区的主题中,无法保证消费者按顺序接收到表的truncate事件和更改事件(创建、更新等)。例如,当消费者从不同的分区读取事件时,它可能会在收到同一张表的截断事件后收到该表的更新事件。仅当主题使用单个分区时才能保证排序。
如果您不想捕获截断事件,请使用该skipped.operations选项将其过滤掉。

7.数据类型映射

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

对于表中的每一列,Debezium 将源数据类型映射到相应事件字段中的文字类型,在某些情况下,映射到语义类型。

使用以下Kafka Connect模式类型之一描述值的字面表示方式:
INT8, INT16, INT32, INT64, FLOAT32, FLOAT64, BOOLEAN, STRING, BYTES, ARRAY, MAP, and STRUCT.
语义类型
通过使用字段的Kafka Connect 架构名称,描述 Kafka Connect 架构如何捕获字段的含义

对于某些 Oracle 大对象(CLOB、NCLOB 和 BLOB)和数字数据类型,您可以通过更改默认配置属性设置来操纵连接器执行类型映射的方式。

四、字符类型

下表描述了连接器如何映射基本字符类型。
Oracle 基本字符类型的映射
CHAR[(M)]、NCHAR[(M)]、NVARCHAR2[(M)]、VARCHAR[(M)]、VARCHAR2[(M)] —— STRING

1.二进制和字符 LOB 类型

Oracle 二进制和字符 LOB 类型的映射
BLOB —— BYTES
CLOB —— STRING
NCLOB —— STRING

2.数值类型

BINARY_FLOAT:FLOAT32
BINARY_DOUBLE:FLOAT64
DECIMAL[(P, S)]:BYTES / INT8 / INT16 / INT32 / INT64

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

Handled 等效于NUMBER(请注意 S 默认为 0 DECIMAL)。
当该decimal.handling.mode属性设置为时double,连接器将DECIMAL值表示为double模式类型为 的 Java 值FLOAT64。
当该decimal.handling.mode属性设置为时string,连接器将 DECIMAL 值表示为其具有架构类型的格式化字符串表示形式STRING。

DOUBLE PRECISION:STRUCT
FLOAT[§]:STRUCT
INTEGER,INT:BYTES org.apache.kafka.connect.data.Decimal

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

NUMBER[(P[, *])]:STRUCT

NUMBER(P, S <= 0):INT8// INT16/ INT32_INT64
NUMBER标度为 0 的列表示整数。负数表示在 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值表示为double模式类型为 的 Java 值FLOAT64。
    当该decimal.handling.mode属性设置为时string,连接器将NUMBER值表示为其具有架构类型的格式化字符串表示形式STRING。

如上所述,Oracle 允许在NUMBER类型中使用负标度。当数字表示为Decimal. Decimal类型包括比例信息,但Avro 规范只允许比例为正值。根据使用的模式注册表,它可能会导致 Avro 序列化失败。为避免此问题,您可以使用NumberToZeroScaleConverter,它将具有负标度的足够高的数字 (P - S >= 19) 转换为Decimal具有零标度的类型。它可以配置如下:

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

默认情况下,数字会转换为Decimal类型 ( zero_scale.decimal.mode=precise),但为了完整起见,还支持其余两种受支持的类型 (double和)string。

3.布尔类型

Oracle 不提供对BOOLEAN数据类型的本机支持。然而,通常的做法是使用具有特定语义的其他数据类型来模拟逻辑数据类型的概念BOOLEAN。
为了使您能够将源列转换为布尔数据类型,Debezium 提供了一个NumberOneToBooleanConverter 自定义转换器,您可以通过以下方式之一使用它:

  • 将所有NUMBER(1)列映射到一个BOOLEAN类型。
  • 使用以逗号分隔的正则表达式列表枚举列的子集。
    要使用这种类型的转换,您必须使用参数设置converters配置属性selector,如以下示例所示:
converters=boolean
boolean.type=io.debezium.connector.oracle.converters.NumberOneToBooleanConverter
boolean.selector=.*MYTABLE.FLAG,.*.IS_ARCHIVED

4.时间类型

除了 Oracle INTERVAL、TIMESTAMP WITH TIME ZONE和TIMESTAMP WITH LOCAL TIME ZONE数据类型之外,连接器转换时态类型的方式取决于time.precision.mode配置属性的值。
当time.precision.mode配置属性设置为adaptive(默认值)时,连接器会根据列的数据类型定义确定时间类型的文字和语义类型,以便事件准确表示数据库中的值:

DATE:INT64 io.debezium.time.Timestamp表示自 UNIX 纪元以来的毫秒数,不包括时区信息。

INTERVAL DAY[(M)] TO SECOND:FLOAT64 io.debezium.time.MicroDuration

一个时间间隔的微秒数,使用365.25 / 12.0每月平均天数的公式。

io.debezium.time.Interval(当interval.handling.mode设置为时string)

模式 之后的区间值的字符串表示形式PYMDTHMS,例如 P1Y2M3DT4H5M6.78S。

当time.precision.mode配置属性设置为时connect,连接器将使用预定义的 Kafka Connect 逻辑类型。当消费者只知道内置的 Kafka Connect 逻辑类型而无法处理可变精度时间值时,这可能很有用。因为 Oracle 支持的精度级别超过了 Kafka Connect 中的逻辑类型支持的级别,如果设置为time.precision.mode,connect当数据库列的小数秒精度值大于 3 时,会导致精度损失。

五、重做日志大小

根据数据库配置,重做日志的大小和数量可能不足以达到可接受的性能。在设置 Debezium Oracle 连接器之前,请确保重做日志的容量足以支持数据库。
数据库重做日志的容量必须足以存储其数据字典。通常,数据字典的大小随着数据库中表和列的数量而增加。如果重做日志容量不足,数据库和 Debezium 连接器都可能遇到性能问题。

深入理解Oracle数据库重做日志可以参考博主下面这篇博客:

  • Oracle数据库从入门到精通系列之四:重做日志文件

六、为连接器创建用户

要让 Debezium Oracle 连接器捕获更改事件,它必须以具有特定权限的 Oracle LogMiner 用户身份运行。以下示例显示了用于在多租户数据库模型中为连接器创建 Oracle 用户帐户的 SQL。

创建连接器的 LogMiner 用户

sqlplus sys/top_secret@//localhost:1521/ORCLCDB as sysdba
  CREATE TABLESPACE logminer_tbs DATAFILE '/opt/oracle/oradata/ORCLCDB/logminer_tbs.dbf'
    SIZE 25M REUSE AUTOEXTEND ON MAXSIZE UNLIMITED;
  exit;

sqlplus sys/top_secret@//localhost:1521/ORCLPDB1 as sysdba
  CREATE TABLESPACE logminer_tbs DATAFILE '/opt/oracle/oradata/ORCLCDB/ORCLPDB1/logminer_tbs.dbf'
    SIZE 25M REUSE AUTOEXTEND ON MAXSIZE UNLIMITED;
  exit;

sqlplus sys/top_secret@//localhost:1521/ORCLCDB as sysdba

  CREATE USER c##dbzuser IDENTIFIED BY dbz
    DEFAULT TABLESPACE logminer_tbs
    QUOTA UNLIMITED ON logminer_tbs
    CONTAINER=ALL;

  GRANT CREATE SESSION TO c##dbzuser CONTAINER=ALL; 1
  GRANT SET CONTAINER TO c##dbzuser CONTAINER=ALL; 
  GRANT SELECT ON V_$DATABASE to c##dbzuser CONTAINER=ALL; 
  GRANT FLASHBACK ANY TABLE TO c##dbzuser CONTAINER=ALL; 
  GRANT SELECT ANY TABLE TO c##dbzuser CONTAINER=ALL; 
  GRANT SELECT_CATALOG_ROLE TO c##dbzuser CONTAINER=ALL; 
  GRANT EXECUTE_CATALOG_ROLE TO c##dbzuser CONTAINER=ALL; 
  GRANT SELECT ANY TRANSACTION TO c##dbzuser CONTAINER=ALL; 
  GRANT LOGMINING TO c##dbzuser CONTAINER=ALL; 

  GRANT CREATE TABLE TO c##dbzuser CONTAINER=ALL; 
  GRANT LOCK ANY TABLE TO c##dbzuser CONTAINER=ALL; 
  GRANT CREATE SEQUENCE TO c##dbzuser CONTAINER=ALL; 

  GRANT EXECUTE ON DBMS_LOGMNR TO c##dbzuser CONTAINER=ALL; 
  GRANT EXECUTE ON DBMS_LOGMNR_D TO c##dbzuser CONTAINER=ALL; 

  GRANT SELECT ON V_$LOG TO c##dbzuser CONTAINER=ALL; 
  GRANT SELECT ON V_$LOG_HISTORY TO c##dbzuser CONTAINER=ALL; 
  GRANT SELECT ON V_$LOGMNR_LOGS TO c##dbzuser CONTAINER=ALL; 
  GRANT SELECT ON V_$LOGMNR_CONTENTS TO c##dbzuser CONTAINER=ALL; 
  GRANT SELECT ON V_$LOGMNR_PARAMETERS TO c##dbzuser CONTAINER=ALL; 
  GRANT SELECT ON V_$LOGFILE TO c##dbzuser CONTAINER=ALL; 
  GRANT SELECT ON V_$ARCHIVED_LOG TO c##dbzuser CONTAINER=ALL; 
  GRANT SELECT ON V_$ARCHIVE_DEST_STATUS TO c##dbzuser CONTAINER=ALL; 
  GRANT SELECT ON V_$TRANSACTION TO c##dbzuser CONTAINER=ALL; 

  GRANT SELECT ON V_$MYSTAT TO c##dbzuser CONTAINER=ALL; 
  GRANT SELECT ON V_$STATNAME TO c##dbzuser CONTAINER=ALL; 

  exit;

创建会话:使连接器能够连接到 Oracle。
设置容器:使连接器能够在可插入数据库之间切换。这仅在 Oracle 安装启用了容器数据库支持 (CDB) 时才需要。
在 V_ D A T A B A S E 上选择:使连接器能够读取表 V DATABASE 上选择:使连接器能够读取表V DATABASE上选择:使连接器能够读取表VDATABASE。
闪回任何表格:使连接器能够执行闪回查询,这是连接器执行数据初始快照的方式。
选择任何表格:使连接器能够读取任何表。
选择目录角色:使连接器能够读取 Oracle LogMiner 会话所需的数据字典。
执行目录角色:使连接器能够将数据字典写入 Oracle 重做日志,这是跟踪架构更改所必需的。
选择任何交易:使快照进程能够针对任何事务执行闪回快照查询。什么时候FLASHBACK ANY TABLE授予,这个也应该授予。
日志挖掘:此角色是在较新版本的 Oracle 中添加的,作为授予对 Oracle LogMiner 及其包的完全访问权限的一种方式。在没有此角色的旧版 Oracle 上,您可以忽略此授权。
创建表:使连接器能够在其默认表空间中创建其刷新表。刷新表允许连接器显式控制将 LGWR 内部缓冲区刷新到磁盘。
锁定任何表:使连接器能够在模式快照期间锁定表。如果通过配置显式禁用快照锁,则可以安全地忽略此授权。
创建序列:使连接器能够在其默认表空间中创建序列。
在 DBMS_LOGMNR 上执行:使连接器能够运行DBMS_LOGMNR包中的方法。这是与 Oracle LogMiner 交互所必需的。在较新版本的 Oracle 上,这是通过LOGMINING角色授予的,但在旧版本上,这必须明确授予。
在 DBMS_LOGMNR_D 上执行:使连接器能够运行DBMS_LOGMNR_D包中的方法。这是与 Oracle LogMiner 交互所必需的。在较新版本的 Oracle 上,这是通过LOGMINING角色授予的,但在旧版本上,这必须明确授予。
15 至 25 选择 V_$… 。:使连接器能够读取这些表。连接器必须能够读取有关 Oracle 重做和存档日志以及当前事务状态的信息,以准备 Oracle LogMiner 会话。没有这些授权,连接器就无法运行。

七、故障转移数据库

在 Oracle 生产故障的情况下,通常存在逻辑或物理备用数据库。当发生故障并将备用实例提升为生产实例时,必须打开数据库以进行读/写事务,然后 Debezium Oracle 连接器才能连接到数据库。
在物理备用的情况下,备用是生产的精确副本,这意味着 SCN 值是相同的。使用物理备用数据库时,重新配置 Debezium Oracle 连接器以在数据库打开后使用备用数据库的主机名就足够了。
在逻辑备用的情况下,备用不是生产数据库的精确副本,因此备用中的 SCN 偏移量与生产数据库中的不同。如果您使用逻辑备用,为了帮助确保 Debezium 不会错过任何更改事件,在数据库打开后,配置一个新的连接器并执行一个新的数据库快照。

八、Debezium Oracle 连接器配置

通常,您通过提交指定连接器配置属性的 JSON 请求来注册 Debezium Oracle 连接器。以下示例显示了一个 JSON 请求,用于server1在端口 1521 上注册一个逻辑名称为 Debezium Oracle 连接器的实例:
您可以选择为数据库中的模式和表的子集生成事件。或者,您可以忽略、屏蔽或截断包含敏感数据、大于指定大小或您不需要的列。

{
    "name": "inventory-connector",  
    "config": {
        "connector.class" : "io.debezium.connector.oracle.OracleConnector",  
        "database.hostname" : "",  
        "database.port" : "1521",  
        "database.user" : "c##dbzuser",  
        "database.password" : "dbz",   
        "database.dbname" : "ORCLCDB",  
        "topic.prefix" : "server1",  
        "tasks.max" : "1",  
        "database.pdb.name" : "ORCLPDB1",  
        "schema.history.internal.kafka.bootstrap.servers" : "kafka:9092", 
        "schema.history.internal.kafka.topic": "schema-changes.inventory"  
    }
}
  1. 向 Kafka Connect 服务注册时分配给连接器的名称。
  2. 此 Oracle 连接器类的名称。
  3. Oracle 实例的地址。
  4. Oracle 实例的端口号。
  5. Oracle 用户的名称,如为连接器创建用户中指定的那样。
  6. Oracle 用户的密码,如为连接器创建用户中指定的那样。
  7. 要从中捕获更改的数据库的名称。标识并为连接器从中捕获更改的 Oracle 数据库服务器提供命名空间的主题前缀。
  8. 为此连接器创建的最大任务数。
  9. 连接器从中捕获更改的 Oracle 可插拔数据库的名称。仅用于容器数据库 (CDB) 安装。
  10. 此连接器用于将 DDL 语句写入和恢复到数据库模式历史主题的 Kafka 代理列表。
  11. 连接器写入和恢复 DDL 语句的数据库架构历史主题的名称。本主题仅供内部使用,消费者不应使用。

在前面的示例中,database.hostname和database.port属性用于定义与数据库主机的连接。但是,在更复杂的 Oracle 部署中,或在使用透明网络底层 (TNS) 名称的部署中,您可以使用指定 JDBC URL 的替代方法。
下面的 JSON 示例显示了与前面示例相同的配置,只是它使用 JDBC URL 连接到数据库。

示例:使用 JDBC URL 连接到数据库的 Debezium Oracle 连接器配置

{
    "name": "inventory-connector",
    "config": {
        "connector.class" : "io.debezium.connector.oracle.OracleConnector",
        "tasks.max" : "1",
        "topic.prefix" : "server1",
        "database.user" : "c##dbzuser",
        "database.password" : "dbz",
        "database.url": "jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS_LIST=(LOAD_BALANCE=OFF)(FAILOVER=ON)(ADDRESS=(PROTOCOL=TCP)(HOST=)(PORT=1521))(ADDRESS=(PROTOCOL=TCP)(HOST=)(PORT=1521)))(CONNECT_DATA=SERVICE_NAME=)(SERVER=DEDICATED)))",
        "database.dbname" : "ORCLCDB",
        "database.pdb.name" : "ORCLPDB1",
        "schema.history.internal.kafka.bootstrap.servers" : "kafka:9092",
        "schema.history.internal.kafka.topic": "schema-changes.inventory"
    }
}

您可以使用命令将此配置发送POST到正在运行的 Kafka Connect 服务。该服务记录配置并启动执行以下操作的连接器任务:

  • 连接到 Oracle 数据库。
  • 读取重做日志。
  • 记录更改事件到 Kafka 主题。

九、添加连接器配置

要开始运行 Debezium Oracle 连接器,请创建连接器配置,并将配置添加到您的 Kafka Connect 集群。
先决条件

  • Oracle 配置为与 Debezium 一起使用。
  • Debezium Oracle 连接器已安装。
    程序
  1. 为 Oracle 连接器创建配置。
  2. 使用Kafka Connect REST API将该连接器配置添加到您的 Kafka Connect 集群。
    结果
    连接器启动后,它会为连接器配置的 Oracle 数据库执行一致的快照。然后,连接器开始为行级操作生成数据更改事件,并将更改事件记录流式传输到 Kafka 主题。

十、可插拔与不可插拔数据库

Oracle 数据库支持以下部署类型:
容器数据库 (CDB)
可以包含多个可插入数据库 (PDB) 的数据库。数据库客户端连接到每个 PDB,就像它是一个标准的非 CDB 数据库一样。
非容器数据库(non-CDB)
标准 Oracle 数据库,不支持创建可插入数据库。

CDB 部署的 Debezium 连接器配置

{
    "config": {
        "connector.class" : "io.debezium.connector.oracle.OracleConnector",
        "tasks.max" : "1",
        "topic.prefix" : "server1",
        "database.hostname" : "",
        "database.port" : "1521",
        "database.user" : "c##dbzuser",
        "database.password" : "dbz",
        "database.dbname" : "ORCLCDB",
        "database.pdb.name" : "ORCLPDB1",
        "schema.history.internal.kafka.bootstrap.servers" : "kafka:9092",
        "schema.history.internal.kafka.topic": "schema-changes.inventory"
    }
}

当您配置 Debezium Oracle 连接器以与 Oracle CDB 一起使用时,您必须为属性指定一个值database.pdb.name,该值命名您希望连接器从中捕获更改的 PDB。对于非 CDB 安装,请勿指定该database.pdb.name属性。

示例:用于非 CDB 部署的 Debezium Oracle 连接器配置

{
    "config": {
        "connector.class" : "io.debezium.connector.oracle.OracleConnector",
        "tasks.max" : "1",
        "topic.prefix" : "server1",
        "database.hostname" : "",
        "database.port" : "1521",
        "database.user" : "c##dbzuser",
        "database.password" : "dbz",
        "database.dbname" : "ORCLCDB",
        "schema.history.internal.kafka.bootstrap.servers" : "kafka:9092",
        "schema.history.internal.kafka.topic": "schema-changes.inventory"
    }
}

十一、连接器属性

Debezium Oracle 连接器具有许多配置属性,您可以使用这些属性为您的应用程序实现正确的连接器行为。许多属性都有默认值。有关属性的信息组织如下:

  • 所需的 Debezium Oracle 连接器配置属性
  • 数据库模式历史连接器配置属性,控制 Debezium 如何处理它从数据库模式历史主题中读取的事件。
    • 直通数据库架构历史属性
  • 控制数据库驱动程序行为的直通数据库驱动程序属性。

1.所需的 Debezium Oracle 连接器配置属性

属性 默认参数 含义解释
name 连接器的唯一名称。尝试使用相同的名称再次注册将失败。(所有 Kafka Connect 连接器都需要此属性。)
connector.class 连接器的 Java 类的名称。io.debezium.connector.oracle.OracleConnector对于 Oracle 连接器始终使用值。
converters 枚举连接器可以使用的自定义转换器实例的符号名称的逗号分隔列表。
例如,boolean。
tasks.max 1 为此连接器创建的最大任务数。Oracle 连接器始终使用单个任务,因此不使用此值,因此默认值始终可以接受。
database.hostname
database.port
database.user
database.password
database.dbname 要连接的数据库的名称。使用 CDB + PDB 模型时必须是 CDB 名称。
database.url 指定原始数据库 JDBC URL。使用此属性可以灵活地定义该数据库连接。有效值包括原始 TNS 名称和 RAC 连接字符串。
database.pdb.name 要连接的 Oracle 可插拔数据库的名称。仅将此属性用于容器数据库 (CDB) 安装。
topic.prefix 为连接器从中捕获更改的 Oracle 数据库服务器提供命名空间的主题前缀。您设置的值用作连接器发出的所有 Kafka 主题名称的前缀。指定在 Debezium 环境中的所有连接器中唯一的主题前缀。以下字符有效:字母数字字符、连字符、点和下划线。
database.connection.adapter 连接器在流式传输数据库更改时使用的适配器实现。您可以设置以下值:( logminer默认):: 连接器使用本机 Oracle LogMiner API。 xstream:: 连接器使用 Oracle XStreams API。
snapshot.mode 指定连接器用于拍摄捕获表快照的模式。您可以设置以下值:always快照包括捕获表的结构和数据。指定此值以使用每个连接器启动时捕获的表中数据的完整表示来填充主题。initial快照包括捕获表的结构和数据。指定此值以使用捕获表中数据的完整表示来填充主题。如果快照成功完成,则在下一个连接器启动时不会再次执行快照。initial_only快照包括捕获表的结构和数据。连接器执行初始快照然后停止,不处理任何后续更改。schema_only快照仅包含捕获表的结构。如果您希望连接器仅捕获快照之后发生的更改的数据,请指定此值。schema_only_recovery这是已捕获更改的连接器的恢复设置。当您重新启动连接器时,此设置可以恢复损坏或丢失的数据库架构历史主题。您可以定期将其设置为“清理”意外增长的数据库模式历史主题。数据库架构历史主题需要无限保留。请注意,只有在保证自连接器之前关闭的时间点和拍摄快照的时间点以来没有发生模式更改时,才可以安全地使用此模式。快照完成后,连接器继续从数据库的重做日志中读取更改事件,除非snapshot.mode配置为initial_only.
snapshot.locking.mode 控制连接器是否持有表锁以及持有表锁的时间。表锁可防止在连接器执行快照时发生某些类型的更改表操作。您可以设置以下值:
shared启用对表的并发访问,但阻止任何会话获取独占表锁。连接器ROW SHARE在捕获表模式时获取级别锁。none防止连接器在快照期间获取任何表锁。仅当在创建快照期间可能不会发生架构更改时才使用此设置。
snapshot.include.collection.list 可选的、以逗号分隔的正则表达式列表,匹配要包含在快照中的表的完全限定名称 ( )。在使用 LogMiner 实现的环境中,您必须仅使用 POSIX 正则表达式。指定的项目必须在连接器的属性中命名。仅当连接器的属性设置为 以外的值时,此属性才会生效。 此属性不影响增量快照的行为。.table.include.listsnapshot.modenever
为了匹配表的名称,Debezium 应用您指定为锚定正则表达式的正则表达式。也就是说,指定的表达式与表的整个名称字符串匹配;它与表名中可能存在的子字符串不匹配。
schema.include.list 一个可选的、以逗号分隔的正则表达式列表,这些正则表达式匹配您要为其捕获更改的模式的名称。在使用 LogMiner 实现的环境中,您必须仅使用 POSIX 正则表达式。任何未包含在中的模式名称都schema.include.list被排除在捕获其更改之外。默认情况下,所有非系统模式都会捕获它们的更改。为了匹配模式的名称,Debezium 应用您指定为锚定正则表达式的正则表达式。也就是说,指定的表达式与模式的整个名称字符串匹配;它不匹配模式名称中可能存在的子字符串。如果您在配置中包含此属性,则不要同时设置该schema.exclude.list属性。
schema.exclude.list 一个可选的、以逗号分隔的正则表达式列表,这些正则表达式匹配您不想为其捕获更改的模式的名称。在使用 LogMiner 实现的环境中,您必须仅使用 POSIX 正则表达式。任何名称未包含在其中的模式schema.exclude.list都会捕获其更改,系统模式除外。为了匹配模式的名称,Debezium 应用您指定为锚定正则表达式的正则表达式。也就是说,指定的表达式与模式的整个名称字符串匹配;它不匹配模式名称中可能存在的子字符串。如果在配置中包含此属性,请不要设置 schema.include.list 属性。
table.include.list 可选的以逗号分隔的正则表达式列表,匹配要捕获的表的完全限定表标识符。如果您使用 LogMiner 实现,请仅使用具有此属性的 POSIX 正则表达式。设置此属性后,连接器仅捕获指定表中的更改。每个表标识符使用以下格式:.默认情况下,连接器监视每个捕获的数据库中的每个非系统表。为了匹配表的名称,Debezium 应用您指定为锚定正则表达式的正则表达式。也就是说,指定的表达式与表的整个名称字符串匹配;它与表名中可能存在的子字符串不匹配。如果您在配置中包含此属性,则不要同时设置该table.exclude.list属性。
table.exclude.list 可选的以逗号分隔的正则表达式列表,匹配要从监视中排除的表的完全限定表标识符。如果您使用 LogMiner 实现,请仅使用具有此属性的 POSIX 正则表达式。连接器捕获未在排除列表中指定的任何表的更改事件。使用以下格式指定每个表的标识符:..为了匹配表的名称,Debezium 应用您指定为锚定正则表达式的正则表达式。也就是说,指定的表达式与表的整个名称字符串匹配;它与表名中可能存在的子字符串不匹配。如果您在配置中包含此属性,则不要同时设置该table.include.list属性。
column.include.list 一个可选的、以逗号分隔的正则表达式列表,这些正则表达式与要包含在更改事件消息值中的列的完全限定名称相匹配。在使用 LogMiner 实现的环境中,您必须仅使用 POSIX 正则表达式。列的完全限定名称使用以下格式:..主键列始终包含在事件的键中,即使您不使用此属性显式包含其值也是如此。为了匹配列的名称,Debezium 应用您指定为锚定正则表达式的正则表达式。也就是说,指定的表达式与列的整个名称字符串匹配,它不与列名称中可能存在的子字符串匹配。如果您在配置中包含此属性,则不要同时设置该column.exclude.list属性。
skip.messages.without.change 指定当包含的列没有变化时是否跳过发布消息。column.include.list如果按或属性包含的列没有变化,这实际上会过滤消息column.exclude.list。
binary.handling.mode bytes 指定二进制 ( blob) 列在更改事件中的表示方式,包括:bytes将二进制数据表示为字节数组(默认),将base64二进制数据表示为 base64 编码的字符串,将base64-url-safe二进制数据表示为 base64-url-安全编码的字符串,hex表示二进制数据作为十六进制编码 (base16) 字符串
decimal.handling.mode precise NUMBER指定连接器应如何处理和列DECIMAL的浮点值NUMERIC。您可以设置以下选项之一:precise(默认)通过使用java.math.BigDecimal二进制形式的变化事件中表示的值来精确表示值。double用double值表示值。使用double值更容易,但会导致精度损失。string将值编码为格式化字符串。使用该string选项更容易使用,但会导致有关真实类型的语义信息丢失。有关详细信息,请参阅数值类型。
interval.handling.mode numeric 指定连接器应如何处理interval列的值:numeric使用近似微秒数表示间隔。string通过使用字符串模式表示准确地表示间隔PYMDTHMS。例如:P1Y2M3DT4H5M6.78S。
event.processing.failure.handling.mode fail 指定连接器在处理事件期间应如何对异常做出反应。您可以设置以下选项之一:fail传播异常(指示有问题事件的偏移量),导致连接器停止。warn导致跳过有问题的事件。然后记录有问题的事件的偏移量。skip导致跳过有问题的事件。
max.batch.size 2048 一个正整数值,指定在此连接器每次迭代期间要处理的每批事件的最大大小。
max.queue.size 8192 指定阻塞队列可以容纳的最大记录数的正整数值。当 Debezium 读取从数据库流出的事件时,它会在将事件写入 Kafka 之前将其放入阻塞队列中。在连接器接收消息的速度快于将消息写入 Kafka 的速度,或者 Kafka 变得不可用的情况下,阻塞队列可以为从数据库中读取更改事件提供背压。当连接器定期记录偏移量时,将忽略保留在队列中的事件。始终将 的值设置max.queue.size为大于 的值max.batch.size。
max.queue.size.in.bytes 0(禁用) 一个长整数值,指定阻塞队列的最大容量(以字节为单位)。默认情况下,没有为阻塞队列指定容量限制。要指定队列可以消耗的字节数,请将此属性设置为正长值。如果max.queue.size也设置了,则当队列的大小达到任一属性指定的限制时,写入队列将被阻止。例如,设置max.queue.size=1000、 和max.queue.size.in.bytes=5000,当队列包含1000条记录后,或者队列中的记录量达到5000字节后,写入队列被阻塞。
poll.interval.ms 500(0.5 秒) 正整数值,指定连接器在每次迭代期间应等待新更改事件出现的毫秒数。
tombstones.on.delete true 控制删除事件后是否跟有逻辑删除事件。以下值是可能的:true对于每个删除操作,连接器都会发出一个删除事件和一个后续的逻辑删除事件。false对于每个删除操作,连接器仅发出一个删除事件。删除源记录后,逻辑删除事件(默认行为)使 Kafka 能够完全删除在启用了日志压缩的主题中共享已删除行的键的所有事件。
message.key.columns 一个表达式列表,指定连接器用于为它发布到指定表的 Kafka 主题的更改事件记录形成自定义消息键的列。默认情况下,Debezium 使用表的主键列作为它发出的记录的消息键。代替默认值,或为缺少主键的表指定键,您可以基于一个或多个列配置自定义消息键。要为表建立自定义消息键,请列出表,然后列出要用作消息键的列。每个列表条目都采用以下格式:: ,要使表键基于多个列名,请在列名之间插入逗号。每个完全限定的表名都是以下格式的正则表达式: 该属性可以包含多个表的条目。使用分号分隔列表中的表条目。 以下示例设置表的消息键.inventory.customers和purchase.orders:inventory.customers:pk1,pk2;(.*).purchaseorders:pk3,pk4对于表inventory.customer,列pk1和pk2被指定为消息键。对于purchaseorders任何模式中的表,列pk3和pk4服务器作为消息键。用于创建自定义消息键的列数没有限制。但是,最好使用指定唯一键所需的最小数量。
heartbeat.interval.ms 0
heartbeat.action.query
log.mining.strategy redo_log_catalog 缓冲区类型控制连接器如何管理缓冲事务数据。memory- 使用 JVM 进程的堆来缓冲所有事务数据。如果您不希望连接器处理大量长时间运行的事务或大型事务,请选择此选项。当此选项处于活动状态时,缓冲区状态不会在重新启动后保持不变。重启后,从当前偏移量的 SCN 值重新创建缓冲区。infinispan_embedded- 此选项使用嵌入式 Infinispan 缓存来缓冲交易数据并将其保存到磁盘。 infinispan_remote- 此选项使用远程 Infinispan 集群来缓冲交易数据并将其保存到磁盘。
log.mining.buffer.type memory 缓冲区类型控制连接器如何管理缓冲事务数据。memory- 使用 JVM 进程的堆来缓冲所有事务数据。如果您不希望连接器处理大量长时间运行的事务或大型事务,请选择此选项。当此选项处于活动状态时,缓冲区状态不会在重新启动后保持不变。重启后,从当前偏移量的 SCN 值重新创建缓冲区。infinispan_embedded- 此选项使用嵌入式 Infinispan 缓存来缓冲交易数据并将其保存到磁盘。infinispan_remote- 此选项使用远程 Infinispan 集群来缓冲交易数据并将其保存到磁盘。
signal.data.collection 用于向连接器发送信号的数据集合的完全限定名称。当您将此属性用于 Oracle 可插拔数据库 (PDB) 时,请将其值设置为根数据库的名称。使用以下格式指定集合名称:..
incremental.snapshot.chunk.size 1024 连接器在增量快照块期间提取并读入内存的最大行数。增加块大小可提供更高的效率,因为快照运行的快照查询数量更大。但是,更大的块大小也需要更多内存来缓冲快照数据。将块大小调整为可在您的环境中提供最佳性能的值。
topic.naming.strategy io.debezium.schema.SchemaTopicNamingStrategy 应用于确定数据更改、模式更改、事务、心跳事件等主题名称的 TopicNamingStrategy 类的名称,默认为SchemaTopicNamingStrategy.
topic.delimiter . 指定主题名称的分隔符,默认为…
topic.cache.size 10000 用于在有界并发哈希映射中保存主题名称的大小。此缓存将有助于确定与给定数据集合对应的主题名称。
topic.heartbeat.prefix __debezium-heartbeat 控制连接器将心跳消息发送到的主题的名称。主题名称具有以下模式:topic.heartbeat.prefix。topic.prefix例如,如果主题前缀是fulfillment,则默认主题名称是__debezium-heartbeat.fulfillment。
topic.transaction transaction 控制连接器将事务元数据消息发送到的主题的名称。主题名称具有以下模式:topic.prefix。topic.transaction例如,如果主题前缀是fulfillment,则默认主题名称是fulfillment.transaction。
snapshot.max.threads 1 指定连接器在执行初始快照时使用的线程数。要启用并行初始快照,请将该属性设置为大于 1 的值。在并行初始快照中,连接器同时处理多个表。此功能正在孵化。

2.Debezium Oracle 连接器数据库架构历史配置属性

Debezium 提供一组 schema.history.internal.* 属性来控制连接器如何与模式历史主题交互。

下表描述了用于配置 Debezium 连接器的 schema.history.internal 属性。

属性 默认参数 含义解释
schema.history.internal.kafka.topic 连接器存储数据库架构历史记录的 Kafka 主题的全名。
schema.history.internal.kafka.bootstrap.servers 连接器用于建立与 Kafka 集群的初始连接的主机/端口对列表。此连接用于检索以前由连接器存储的数据库模式历史记录,以及用于编写从源数据库读取的每个 DDL 语句。每对都应指向 Kafka Connect 进程使用的同一个 Kafka 集群。
schema.history.internal.kafka.recovery.poll.interval.ms 一个整数值,指定连接器在启动/恢复期间轮询持久数据时应等待的最大毫秒数。默认值为 100 毫秒。
schema.history.internal.kafka.query.timeout.ms 一个整数值,指定连接器在使用 Kafka 管理客户端获取集群信息时应等待的最大毫秒数
schema.history.internal.kafka.create.timeout.ms 一个整数值,指定连接器在使用 Kafka 管理客户端创建 kafka 历史主题时应等待的最大毫秒数。
schema.history.internal.kafka.create.timeout.ms 在连接器恢复因错误而失败之前,连接器应尝试读取持久历史数据的最大次数。未接收到数据后等待的最长时间为recovery.attempts× recovery.poll.interval.ms。
schema.history.internal.skip.unparseable.ddl 一个布尔值,指定连接器是应忽略格式错误或未知的数据库语句,还是应停止处理以便人工修复问题。安全默认值是false. 跳过应谨慎使用,因为它可能会在处理二进制日志时导致数据丢失或损坏。
schema.history.internal.store.only.captured.tables.ddl 一个布尔值,指定连接器是否应记录来自指定模式或数据库的所有 DDL 语句true仅记录那些与 Debezium 捕获其更改的表相关的 DDL 语句。小心设置为true,因为如果您更改捕获其更改的表,则可能需要缺少数据。
安全默认值是false.
schema.history.internal.store.only.captured.databases.ddl 一个布尔值,指定连接器是否应记录所有 DDL 语句true仅记录那些与 Debezium 捕获更改的数据库/模式表相关的 DDL 语句。false将存储所有传入的 DDL 语句。

十二、XStreams 支持

默认情况下,Debezium Oracle 连接器使用本机 Oracle LogMiner 获取更改。连接器可以切换为使用 Oracle XStream。要将连接器配置为使用 Oracle XStream,您必须应用不同于您使用 LogMiner 的特定数据库和连接器配置。
先决条件

  • 要使用 XStream API,您必须拥有 GoldenGate 产品的许可证。不需要安装 GoldenGate。

1.准备数据库

Oracle XStream 所需的配置

ORACLE_SID=ORCLCDB dbz_oracle sqlplus /nolog

CONNECT sys/top_secret AS SYSDBA
alter system set db_recovery_file_dest_size = 5G;
alter system set db_recovery_file_dest = '/opt/oracle/oradata/recovery_area' scope=spfile;
alter system set enable_goldengate_replication=true;
shutdown immediate
startup mount
alter database archivelog;
alter database open;
-- Should show "Database log mode: Archive Mode"
archive log list

exit;

此外,必须为捕获的表或数据库启用补充日志记录,以便数据更改能够捕获更改的数据库行之前的状态。下面说明如何在特定表上进行配置,这是最大限度减少 Oracle 重做日志中捕获的信息量的理想选择。

ALTER TABLE inventory.customers ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;

2.为连接器创建 XStream 用户

Debezium Oracle 连接器要求为用户帐户设置特定权限,以便连接器可以捕获更改事件。下面使用多租户数据库模型简要描述这些用户配置。

创建 XStream 管理员用户

sqlplus sys/top_secret@//localhost:1521/ORCLCDB as sysdba
  CREATE TABLESPACE xstream_adm_tbs DATAFILE '/opt/oracle/oradata/ORCLCDB/xstream_adm_tbs.dbf'
    SIZE 25M REUSE AUTOEXTEND ON MAXSIZE UNLIMITED;
  exit;

sqlplus sys/top_secret@//localhost:1521/ORCLPDB1 as sysdba
  CREATE TABLESPACE xstream_adm_tbs DATAFILE '/opt/oracle/oradata/ORCLCDB/ORCLPDB1/xstream_adm_tbs.dbf'
    SIZE 25M REUSE AUTOEXTEND ON MAXSIZE UNLIMITED;
  exit;

sqlplus sys/top_secret@//localhost:1521/ORCLCDB as sysdba
  CREATE USER c##dbzadmin IDENTIFIED BY dbz
    DEFAULT TABLESPACE xstream_adm_tbs
    QUOTA UNLIMITED ON xstream_adm_tbs
    CONTAINER=ALL;

  GRANT CREATE SESSION, SET CONTAINER TO c##dbzadmin CONTAINER=ALL;

  BEGIN
     DBMS_XSTREAM_AUTH.GRANT_ADMIN_PRIVILEGE(
        grantee                 => 'c##dbzadmin',
        privilege_type          => 'CAPTURE',
        grant_select_privileges => TRUE,
        container               => 'ALL'
     );
  END;
  /

  exit;

创建连接器的 XStream 用户

sqlplus sys/top_secret@//localhost:1521/ORCLCDB as sysdba
  CREATE TABLESPACE xstream_tbs DATAFILE '/opt/oracle/oradata/ORCLCDB/xstream_tbs.dbf'
    SIZE 25M REUSE AUTOEXTEND ON MAXSIZE UNLIMITED;
  exit;

sqlplus sys/top_secret@//localhost:1521/ORCLPDB1 as sysdba
  CREATE TABLESPACE xstream_tbs DATAFILE '/opt/oracle/oradata/ORCLCDB/ORCLPDB1/xstream_tbs.dbf'
    SIZE 25M REUSE AUTOEXTEND ON MAXSIZE UNLIMITED;
  exit;

sqlplus sys/top_secret@//localhost:1521/ORCLCDB as sysdba
  CREATE USER c##dbzuser IDENTIFIED BY dbz
    DEFAULT TABLESPACE xstream_tbs
    QUOTA UNLIMITED ON xstream_tbs
    CONTAINER=ALL;

  GRANT CREATE SESSION TO c##dbzuser CONTAINER=ALL;
  GRANT SET CONTAINER TO c##dbzuser CONTAINER=ALL;
  GRANT SELECT ON V_$DATABASE to c##dbzuser CONTAINER=ALL;
  GRANT FLASHBACK ANY TABLE TO c##dbzuser CONTAINER=ALL;
  GRANT SELECT_CATALOG_ROLE TO c##dbzuser CONTAINER=ALL;
  GRANT EXECUTE_CATALOG_ROLE TO c##dbzuser CONTAINER=ALL;
  exit;

3.创建 XStream 出站服务器

创建一个XStream 出站服务器 (如果有正确的权限,这可能会由连接器自动完成):
创建 XStream 出站服务器

sqlplus c##dbzadmin/dbz@//localhost:1521/ORCLCDB
DECLARE
  tables  DBMS_UTILITY.UNCL_ARRAY;
  schemas DBMS_UTILITY.UNCL_ARRAY;
BEGIN
    tables(1)  := NULL;
    schemas(1) := 'debezium';
  DBMS_XSTREAM_ADM.CREATE_OUTBOUND(
    server_name     =>  'dbzxout',
    table_names     =>  tables,
    schema_names    =>  schemas);
END;
/
exit;

设置 XStream 出站服务器以从可插入数据库捕获更改时,source_container_name应提供指定可插入数据库名称的参数。

配置 XStream 用户帐户以连接到 XStream 出站服务器

sqlplus sys/top_secret@//localhost:1521/ORCLCDB as sysdba
BEGIN
  DBMS_XSTREAM_ADM.ALTER_OUTBOUND(
    server_name  => 'dbzxout',
    connect_user => 'c##dbzuser');
END;
/
exit;

笔记:
单个 XStream 出站服务器不能由多个 Debezium Oracle 连接器共享。每个连接器都需要配置一个唯一的 XStream 出站连接器。

4.配置 XStream 适配器

默认情况下,Debezium 使用 Oracle LogMiner 从 Oracle 获取更改事件。您可以调整连接器配置以使连接器能够使用 Oracle XStreams 适配器。

以下配置示例添加属性database.connection.adapter并使database.out.server.name连接器能够使用 XStream API 实现。

{
    "name": "inventory-connector",
    "config": {
        "connector.class" : "io.debezium.connector.oracle.OracleConnector",
        "tasks.max" : "1",
        "topic.prefix" : "server1",
        "database.hostname" : "",
        "database.port" : "1521",
        "database.user" : "c##dbzuser",
        "database.password" : "dbz",
        "database.dbname" : "ORCLCDB",
        "database.pdb.name" : "ORCLPDB1",
        "schema.history.internal.kafka.bootstrap.servers" : "kafka:9092",
        "schema.history.internal.kafka.topic": "schema-changes.inventory",
        "database.connection.adapter": "xstream",
        "database.out.server.name" : "dbzxout"
    }
}

5.获取 Oracle JDBC 驱动程序和 XStream API 文件

Debezium Oracle 连接器需要 Oracle JDBC 驱动程序 ( ojdbc8.jar) 才能连接到 Oracle 数据库。如果连接器使用 XStream 访问数据库,您还必须拥有 XStream API ( xstreams.jar)。许可要求禁止 Debezium 将这些文件包含在 Oracle 连接器存档中。但是,所需的文件可作为 Oracle Instant Client 的一部分免费下载。以下步骤描述了如何下载 Oracle Instant Client 并提取所需的文件。
程序

  1. 从浏览器下载适用于您的操作系统的Oracle Instant Client 包。
  2. 提取存档,然后打开目录。instantclient_
instantclient_21_1/
├── adrci
├── BASIC_LITE_LICENSE
├── BASIC_LITE_README
├── genezi
├── libclntshcore.so -> libclntshcore.so.21.1
├── libclntshcore.so.12.1 -> libclntshcore.so.21.1

...

├── ojdbc8.jar
├── ucp.jar
├── uidrvci
└── xstreams.jar

3.复制ojdbc8.jar和xstreams.jar文件,并将它们添加到/libs目录中,例如kafka/libs.
4.创建一个环境变量 ,LD_LIBRARY_PATH并将其值设置为 Instant Client 目录的路径,例如:

LD_LIBRARY_PATH=/path/to/instant_client/

6.XStream 连接器属性

使用 XStreams 时需要以下配置属性,除非有默认值可用。
database.out.server.name:数据库中配置的 XStream 出站服务器的名称。

十三、Debezium2.X接入Oracle数据库实战详细总结

  • Oracle数据库实战链接后续会补上
  • 更多Debezium实战应用可以参考博主Debezium专栏:Debezium专栏,Debezium实战应用详细总结
  • Debezium系列之第100篇文章:阶段性详细总结对Debezium使用方式的优化,详细介绍对Debezium集群和Kafka集群做的一系列优化
  • Debezium系列之:安装部署debezium详细步骤,并把debezium服务托管到systemctl
  • Debezium系列之:Debezium2.X版本Mysql数据库、Sqlserver数据库、MongoDB数据库debezium connector最新完整的参数配置,并详细介绍参数含义
  • Debezium系列之:打通Debezium2.0以上版本的使用技术

你可能感兴趣的:(日常分享专栏,Debezium系列,Debezium2.X,Oracle数据库,Debezium连接器)