这篇文章是由 3 部分组成的系列文章的一部分,该系列文章探讨如何使用 Debezium 通过 Oracle LogMiner 从 Oracle 数据库中提取更改。在整个系列中,我们将研究为 Debezium for Oracle 设置概念验证 (POC) 部署的所有步骤。我们将讨论设置和配置以及多租户的细微差别。我们还将深入探讨您可能需要了解的任何已知陷阱和问题,以及如何调试特定问题。最后,我们将讨论性能和监控以维持健康的连接器部署。
在整个练习中,我们希望向您展示为 Oracle 部署 Debezium 是多么简单。本系列的安装和设置部分可能看起来相当复杂,但其中许多步骤可能已经存在于预先存在的环境中。我们将深入了解每个步骤,解释如果您使用容器映像部署,这一步是至关重要的。
Oracle 数据库是一种关系数据库管理系统 (RBDMS),该数据库存储并提供对通常相关的数据点的访问。该数据库由Oracle公司开发和销售,是市场上最值得信赖和广泛使用的关系数据库引擎之一,提供可扩展的关系数据库架构。
Oracle 数据库由一组模式组成,这些模式表示数据或模式对象的逻辑结构的集合。模式对象可以是触发器、视图、表、数据类型、序列、过程、函数等中的任何内容。此外,Oracle 12 引入了一种多租户架构,允许单个数据库实例充当多租户容器数据库 (CDB),其中容纳零个、一个或多个客户创建的可插拔数据库 (PDB)。
目标是安装 Oracle 数据库,将 Debezium 连接到 Oracle,并将摄取的更改转换为存储在 Apache Kafka 中的更改事件。
首先,需要一个正在运行的 Oracle 数据库环境。最简单的方法之一是通过部署运行 Oracle 数据库的容器来使用 Docker。 Oracle 已在其容器注册表中发布了此类容器,允许任何人运行数据库并测试驱动它。如果您打算从现有 Oracle 数据库中提取更改,则可以跳过此部分。
Oracle 容器映像都是使用具有多租户功能的 Oracle 预先构建的。这意味着我们将遵循多租户架构的设置。如果您使用的安装不使用多租户,则可能需要进行一些细微的调整。
在本练习中,我们将使用此容器映像。使用 docker pull,使用以下命令通过 Oracle 容器注册表进行身份验证后会拉取映像:
docker pull container-registry.oracle.com/database/enterprise:latest
要启动容器,请使用 docker run 命令。由于数据库容器映像必须首先安装 Oracle 数据库,因此需要多个环境变量,例如数据库 SID、可插入数据库名称和密码。
docker run -d \
--name dbz_oracle21 \
-p 1521:1521 \
-e ORACLE_SID=ORCLCDB \
-e ORACLE_PDB=ORCLPDB1 \
-e ORACLE_PWD=oraclepw \
container-registry.oracle.com/database/enterprise:latest
ORACLE_SID 是指用于标识数据库的系统/服务ID。由于我们使用多租户,因此我们将使用名称 ORCLCDB 来表示容器数据库或 CDB。在Oracle的多租户架构中,ORACLE_PDB是指用于识别可插拔数据库或PDB的系统/服务ID。最后,ORACLE_PWD 指的是 SYS 和 SYSTEM 用户使用的密码,我们稍后将使用它。
容器会将数据保存到容器文件系统上的数据库文件中。移除容器时数据将丢失。
我们明确地将 docker 容器作为守护进程(后台进程)启动。如果您希望查看容器内发生的情况,可以使用命令 docker log -f dbz_oracle21 来跟踪容器的数据库日志。
数据库将在容器内进行配置和安装,这是在新容器启动且不存在初始配置和数据库时发生的。您可以通过在日志中查找类似于以下内容的横幅来了解安装是否成功:
#########################
DATABASE IS READY TO USE!
#########################
至此,安装已结束,可以安全地继续下一部分。
要从 Oracle 数据库获取更改,需要多种数据库配置。如果您使用的是预先存在的环境,则可以跳过其中一些步骤。
需要进行以下配置:
Oracle 将已填充的一组重做日志(数据库事务日志)保存到一个或多个脱机目的地,统称为归档重做日志或归档日志。主数据库中的主要更改将使用存档日志复制到逻辑或物理备用环境。
当重做日志填满并存档时,就会发生日志切换。 Debezium 吸收重做日志和归档日志中的更改。当重做日志归档时,Debezium 需要访问归档日志才能完成重做条目的处理。
安装 Oracle 部分中使用的 Oracle 容器注册表映像未启用存档日志记录。如果您使用其他映像或预先存在的环境,则必须检查是否启用了存档日志记录。要检查状态,请使用 ORACLE_PWD 安装期间定义的 SYS 用户和密码连接到 ORCLCDB 数据库并执行以下查询:
SELECT LOG_MODE FROM V$DATABASE
如果该列包含 ARCHIVELOG,则启用归档日志记录。如果该列包含值 NOARCHIVELOG,则未启用归档日志记录,并且需要进一步配置。
在设置Oracle归档日志时,我们不仅需要启用日志记录功能,还需要在磁盘上指定一个位置来存储日志。如果您使用的是预先存在的环境,则需要咨询数据库管理员。大多数数据库服务器使用特殊路径存储归档日志文件,您需要知道是否使用 Oracle 自动存储管理 (ASM),或者数据库服务器上哪个卷有足够的空间。
让我们打开 Oracle 数据库容器的终端。我们希望使用 SQL*Plus 连接到数据库容器,以使用允许轻松卸载和重新启动数据库的客户端。因此,在新终端中执行:
docker exec -it dbz_oracle21 -e ORACLE_SID=ORCLCDB sqlplus sys as sysdba
如果您连接到现有的 Oracle 环境,您还可以通过 ssh 到数据库服务器的 shell 来运行 SQL*Plus。
上面的命令将启动 Oracle 的 SQL*Plus,一个命令行 Oracle SQL 客户端。客户端将询问您的密码,如果您使用 Oracle 注册表容器,该密码将与 ORACLE_PWD 环境变量或 oraclepw 相同。连接到现有 Oracle 环境时,使用您环境的 SYS 用户密码。
我们需要设置两个数据库参数:
db_recovery_file_dest_size:可用于存储存档日志的字节数。
假设现有归档日志和下一个要归档的日志的大小超过了此配置值。在这种情况下,Oracle 数据库归档程序进程将阻塞。如果所有重做日志都需要归档并且归档程序进程被阻止,则数据库会阻止更改,直到归档程序进程解除阻止为止。使用 RMAN 实用程序删除较旧的存档日志可以解除存档程序进程的阻塞,从而允许存档任何挂起的重做日志。因此,根据数据库保留策略选择合适的大小通常是一个好主意。
db_recovery_file_dest:磁盘上存储归档日志的位置。
该位置必须可由 Oracle 数据库用户(通常称为 oracle 用户)读写。
为了设置这些值,我们将在 SQL*Plus 终端窗口中执行以下 SQL 命令,我们已经以 SYS 用户身份连接到数据库。
ALTER SYSTEM SET db_recovery_file_dest_size = 10G;
ALTER SYSTEM SET db_recovery_file_dest = '/opt/oracle/oradata/ORCLCDB' scope=spfile;
SHUTDOWN IMMEDIATE
STARTUP MOUNT
ALTER DATABASE ARCHIVELOG;
ALTER DATABASE OPEN;
ARCHIVE LOG LIST;
上述ALTER语句调整数据库参数,指定归档日志的保留最大为10GB,并且/opt/oracle/oradata/ORCLCDB是存储日志的位置。
SQL*Plus 的最终输出应显示以下内容:
SQL> Database log mode Archive Mode
Automatic archival Enabled
Archive destination USE_DB_RECOVERY_FILE_DEST
Oldest online log sequence 1
Next log sequence to archive 3
Current log sequence 3
归档日志的配置完成,当发生数据库日志切换时,Oracle ARCH Process 将重新做日志转换为归档日志存储在磁盘上指定的位置。
Oracle 支持多个归档日志目标的概念,允许将重做日志存储在不同的文件位置。使用 Oracle DataGuard 将归档日志副本传输到辅助服务器以进行灾难恢复或商业智能时,多个存储位置是很常见的。我们不会在这篇博文中介绍如何配置它,但值得注意的是,该功能是存在的并且可能会有所帮助。
Oracle 的事务日志称为重做日志。这些日志至关重要,因为它们在数据库崩溃或介质故障时用于恢复到检查点。不幸的是,Oracle 容器镜像通常使用对 Debezium 没有用的重做日志配置。
Debezium 的 Oracle 连接器有两种日志挖掘策略。该策略控制连接器如何与 Oracle LogMiner 交互以及连接器如何接收架构和表更改。
重做日志目录:数据字典将定期写入重做日志,从而随着时间的推移生成更高的归档日志。此设置可以跟踪 DDL 更改,因此如果表的架构发生更改,这将是实现该目的的理想策略。
在线目录:
使用 online_catalog 模式时,您可以安全地完全跳过此步骤。
当使用 redo_log_catalog 模式(默认)时,重做日志大小对于降低日志切换频率至关重要。当发生日志切换时,LogMiner 会话将重新启动,并在重做日志中重建数据字典。该字典由 LogMiner 读回,并用于在会话重新启动时跟踪 DDL 更改,这可能会导致在填充字典表时出现轻微的初始会话延迟。总体而言,当重做日志足够大以将数据字典写入单个日志文件时,您将获得更好的性能。
Oracle 容器注册表映像配置有 200MB 的重做日志大小。使用默认挖掘策略时,此默认大小太小,因此我们将对此进行调整,使日志使用 400MB 的大小。
当使用没有多租户安装的 Oracle 时,使用 400MB 可能仍然稍小,因为在启用多租户时,根数据库中存在大量基表,但可插拔数据库中不存在这些基表。如果您要从至少没有多租户的 Oracle 环境中提取更改,请改用 500MB。
无论多租户如何,这些值在您的生产环境中都应该更加重要。您的 DBA 将能够使用 Oracle 的规模调整指南根据日志切换频率和系统负载确定最佳值。
在进行任何更改之前,必须检查环境的当前状态。在启用存档日志记录的同一终端中,执行以下 SQL 以确定当前日志大小。
SELECT GROUP#, BYTES/1024/1024 SIZE_MB, STATUS FROM V$LOG ORDER BY 1;
Oracle 容器注册表映像将返回以下输出:
GROUP# SIZE_MB STATUS
---------- ---------- ----------------
1 200 INACTIVE
2 200 INACTIVE
3 200 CURRENT
此输出告诉我们有 3 个日志组,每个组的每个日志消耗 200MB 的空间。此外,与每个组关联的状态至关重要,因为它代表该日志的当前状态。
下面对日志状态进行详细介绍:
现在,使用同一终端窗口,执行以下 SQL 以确定重做日志的文件名和位置。
SELECT GROUP#, MEMBER FROM V$LOGFILE ORDER BY 1, 2;
Oracle 容器注册表映像将返回以下输出:
GROUP# MEMBER
---------- ---------------------------------------------------
1 /opt/oracle/oradata/ORCLCDB/redo01.log
2 /opt/oracle/oradata/ORCLCDB/redo02.log
3 /opt/oracle/oradata/ORCLCDB/redo03.log
我们可以从中得知,每个日志组都包含一个重做日志。 Oracle 确实支持每组多个日志的概念,从而允许所谓的多路复用。您通常只会在生产环境中看到这种情况,偶尔在测试环境中看到这种情况,但在开发或容器环境中很少看到这种情况。
目标是将 V$LOG 表中的 BYTES 列调整为 400MB。不幸的是,进行此调整的唯一方法是删除并重新创建日志组,并且只有当组的状态为 INACTIVE 或 UNUSED 时才可能实现此操作。由于上面的日志组 1 处于非活动状态,因此我们将从它开始,但您可以按任意顺序对日志组安全地执行此过程。
在运行 SQL*Plus 的终端中,执行以下命令:
ALTER DATABASE CLEAR LOGFILE GROUP 1;
ALTER DATABASE DROP LOGFILE GROUP 1;
ALTER DATABASE ADD LOGFILE GROUP 1 ('/opt/oracle/oradata/ORCLCDB/redo01.log') size 400M REUSE;
这将删除并重新创建大小为 400MB 的日志组。我们将在 VLOGFILE 表的 MEMBER 列中使用相同的日志文件名。如果数据库使用多路复用,每个日志组有多个日志文件,请使用逗号分隔的文件名列表来注册每个日志文件。
对所有日志组继续执行上述过程,相应地更改日志组和文件名,直到所有 INACTIVE 或 UNUSED 组的大小为 400MB。一旦所有需要更改的内容都是当前的,您可以使用以下 SQL 在数据库上发出日志切换,将数据库前进到下一个重做日志:
ALTER SYSTEM SWITCH LOGFILE;
如果您重新检查 V$LOG 中日志的大小,您将看到如下所示的输出:
SQL> SELECT GROUP#, BYTES/1024/1024 SIZE_MB, STATUS FROM V$LOG ORDER BY 1;
GROUP# SIZE_MB STATUS
---------- ---------- ----------------
1 400 CURRENT
2 400 UNUSED
3 200 ACTIVE
现在我们需要等待数据库最终将日志组3的状态切换为INACTIVE。切换可能需要几分钟的时间,因此请耐心等待并定期重新检查尺寸。一旦状态达到 INACTIVE,请使用相同的过程修改最终日志组和文件名。
在最终日志组之后对 V$LOG 表进行最后一次检查,我们将看到所有内容都按顺序排列:
SQL> SELECT GROUP#, BYTES/1024/1024 SIZE_MB, STATUS FROM V$LOG ORDER BY 1;
GROUP# SIZE_MB STATUS
---------- ---------- ----------------
1 400 CURRENT
2 400 UNUSED
3 400 UNUSED
此时,我们已经修改了所有重做日志大小,减少了 Debezium 执行数据字典构建步骤时日志切换的频率。
Oracle 重做日志主要用于实例和介质恢复,因为这些操作所需的数据会自动记录。默认情况下无法使用 LogMiner,因为 Oracle 不提供任何开箱即用的补充日志数据。由于 Debezium 依赖 LogMiner,因此必须至少启用补充日志记录,Debezium 才能为 Oracle 执行任何更改数据捕获。
可以使用两种不同的策略来设置补充日志记录:
为了让 Debezium 与 LogMiner 交互并使用链接行和各种存储安排,必须在最低级别启用数据库补充日志记录。要启用此级别,请在当前 SQL*Plus 终端中执行以下 SQL:
ALTER DATABASE ADD SUPPLEMENTAL LOG DATA;
当我们讨论配置连接器时,我们将在后面的部分中介绍基于表的补充日志记录。
为了让 Debezium 连接器捕获更改事件,它必须建立与数据库的 JDBC 连接并执行一系列 LogMiner API。用户帐户将需要特定权限才能访问这些 LogMiner API 并从捕获的表中收集数据。
当使用多租户架构时,正如 Oracle 容器注册表映像所示,我们实际上必须使用两个数据库:ORCLCDB(容器或根数据库)和 ORCLPDB1(可插入数据库)。所有捕获的表都将从 PDB 内创建和维护,但有时连接器需要访问根数据库以读取特定的系统表。
因此,在多租户架构中,我们必须首先设置我们的用户帐户将使用的两个表空间。要创建这些表空间,请从 SQL*Plus 终端中执行以下 SQL:
CONNECT sys/oraclepw@ORCLCDB as sysdba;
CREATE TABLESPACE logminer_tbs DATAFILE '/opt/oracle/oradata/ORCLCDB/logminer_tbs.dbf'
SIZE 25M REUSE AUTOEXTEND ON MAXSIZE UNLIMITED;
CONNECT sys/oraclepw@ORCLPDB1 as sysdba;
CREATE TABLESPACE logminer_tbs DATAFILE '/opt/oracle/oradata/ORCLCDB/ORCLPDB1/logminer_tbs.dbf'
SIZE 25M REUSE AUTOEXTEND ON MAXSIZE UNLIMITED;
如果部署不在启用多租户的 Oracle 数据库上,则无需在 ORCLPDB1 数据库中创建第二个表空间。此外,请确保为表空间、凭据和数据库 SID 提供的路径对于您的安装来说都是正确的。您可能需要咨询 DBA 以正确创建表空间。
一旦表空间存在,就可以创建用户帐户本身了。如果使用多租户环境,则用户名必须使用common-user前缀,以便Oracle在CDB根数据库和PDB可插拔数据库中都创建它;否则,用户名可以是任何内容。由于我们正在使用容器安装多租户数据库,因此我们将创建一个名为 c##dbzuser 的用户帐户。
CONNECT sys/oraclepw@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;
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 SELECT ANY DICTIONARY 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;
在本系列的这一部分中,我们介绍了 Oracle 是什么以及它为何如此受欢迎。我们还介绍了使用容器安装 Oracle 数据库以及配置 Oracle 实例以允许 Debezium 摄取更改。在本系列的下一部分中,我们将深入探讨在 Apache Kafka Connect 上部署 Debezium Oracle 连接器。