跳到主要内容

Oracle 数据库环境准备

环境信息

维度支持信息说明
Oracle 版本11g12c19c21c当前支持的 Oracle 版本。
部署方式单机 Oracle、Oracle RAC可用于单机场景,也可用于 RAC 场景。
数据库形态Non-CDB当前文档按 Non-CDB 形态说明。
支持的采集插件LogMinerXStream用户可根据场景选择对应采集方式。
RAC + XStream 默认接入方式dedicated service推荐按专用 service 接入。

单机配置

单机 Oracle 使用 LogMiner

数据库侧前置

单机场景下,LogMiner 至少要完成以下准备:

  1. 开启归档日志,并为 FRA 预留空间。FRA 空间计算规则如下:

FRA >= 每小时归档产生量 × 需要保留的小时数 × 1.5~2 倍安全系数 + 其他 FRA 占用

注意:归档日志空间不足会导致数据库异常,请设置合理的归档日志清理策略和磁盘容量监控告警。

alter system set db_recovery_file_dest='/opt/oracle/oradata/recovery_area' scope=spfile;
alter system set db_recovery_file_dest_size=100G scope=spfile;

shutdown immediate;
startup mount;
alter database archivelog;
alter database open;
archive log list;
  1. 开启数据库级 supplemental logging。
alter database add supplemental log data;
alter database add supplemental log data (primary key) columns;
  1. 创建 CDC 用户,并补齐最小权限。
grant create session to flinkuser;
grant create table to flinkuser;
grant create sequence to flinkuser;
grant select any transaction to flinkuser;
grant select any table to flinkuser;
grant select any dictionary to flinkuser;
grant flashback any table to flinkuser;
grant logmining to flinkuser;
grant execute_catalog_role to flinkuser;
grant select_catalog_role to flinkuser;
grant analyze any to flinkuser;
grant execute on dbms_logmnr to flinkuser;
grant execute on dbms_logmnr_d to flinkuser;

alter user flinkuser quota unlimited on users;

grant select on v_$database to flinkuser;
grant select on v_$archived_log to flinkuser;
grant select on v_$log to flinkuser;
grant select on v_$logfile to flinkuser;
grant select on v_$log_history to flinkuser;
grant select on v_$transaction to flinkuser;
grant select on v_$logmnr_logs to flinkuser;
grant select on v_$logmnr_contents to flinkuser;
grant select on v_$logmnr_parameters to flinkuser;
grant select on v_$logmnr_stats to flinkuser;
  1. 对业务表开启表级 supplemental logging,并授权 CDC 用户读取。
alter table orders add supplemental log data (all) columns;
grant select on testuser.orders to flinkuser;

LOG_MINING_FLUSH 怎么处理

  • 常规 Non-CDB 场景下,优先让 connector 自动创建 LOG_MINING_FLUSH
  • 但前提是 CDC 用户有 CREATE TABLE 和表空间配额。
  • 如果你手工建了这张表,结构必须是单列:
LAST_SCN NUMBER(19,0)
  • 结构不对会在初始化或 flush 阶段报错,例如 ORA-00947

作业侧推荐配置

单机 LogMiner 场景,建议按下面的最小模板配:

source:
type: oracle
jdbc.url: jdbc:oracle:thin:@//<host>:<port>/<service>
username: <cdc_user>
password: <cdc_password>
database: <db_name>
tables: <db_name>.<schema>.<table>
scan.startup.mode: initial
debezium.database.connection.adapter: logminer

启动后怎么验收

LogMiner 场景建议最少做 4 个检查:

  1. 查库确认:
    select log_mode, supplemental_log_data_min, supplemental_log_data_pk from v$database;
  2. 查用户权限是否补齐,尤其是 logminingdbms_logmnr*v_$logmnr_*
  3. 对目标表插入一条唯一数据,确认链路能从快照进入增量。
  4. 若后续要做恢复验证,确认归档保留窗口大于作业恢复窗口,避免命中“归档已清理”。

单机 Oracle 使用 XStream

先说明授权前提:

  • XStream 不是 Oracle Database 自带可直接启用的通用能力,使用前需要具备 Oracle 官方对应的 license 授权;
  • Oracle 官方口径是:XStream 通过 Oracle GoldenGate 产品授权,使用 XStream 前应先购买对应 license;
  • 同时,使用 Oracle XStream 的前提还包括具备 Oracle Database Enterprise Edition 授权;
  • 如果现场还没有明确的 Oracle GoldenGate + Oracle Database Enterprise Edition 授权结论,不建议直接启用 XStream 方案,也不要把 enable_goldengate_replication 当成单纯技术参数随意打开;
  • 本文后续步骤只说明技术配置方法,不等同于具备 Oracle 商业授权,请在实施前先和采购、资产管理或 Oracle 销售接口人确认 license 范围。

数据库侧前置

单机 Oracle 切 XStream 前,建议按下面的顺序完成数据库侧准备。

先确认 CDC 基线已经存在

XStream 不是绕开 CDC 基线的捷径。切到 XStream 之前,库里仍然要具备:

  • ARCHIVELOG
  • FORCE LOGGING
  • 数据库级 supplemental logging
  • 业务表级 supplemental logging

如果这些前置还没做,请先按「单机 Oracle 使用 LogMiner」中的数据库侧前置说明补齐,再继续配置 XStream。

建议先执行下面的查询:

select log_mode, force_logging, supplemental_log_data_min, supplemental_log_data_pk
from v$database;

业务表侧建议再检查一次:

select table_name, log_group_name, always
from user_log_groups
order by table_name, log_group_name;

如果这里查不到你要同步的表,先回到业务 schema 上执行表级 supplemental log data (all) columns。这一步和 LogMiner 一样,不能省略。

sysdba 登录数据库

建议以 Oracle 软件用户进入数据库,再用 sqlplus / as sysdba 执行后续操作。当前团队已验证过的典型操作方式是:

su - oracle
export ORACLE_HOME=/u01/app/oracle/product/19.0.0/dbhome_1
export ORACLE_SID=ORCL19
export PATH=$ORACLE_HOME/bin:$PATH
sqlplus / as sysdba

如果你是单机环境,ORACLE_SID 改成你自己的实例名即可;不需要照搬 ORCL19

开启 XStream 所需数据库参数

XStream 至少需要打开 enable_goldengate_replication,并显式配置 streams_pool_size。当前团队已验证通过的口径是 3G

alter system set enable_goldengate_replication = true scope = both sid = '*';
alter system set streams_pool_size=3G scope=both;

执行后,建议立刻核对:

show parameter enable_goldengate_replication;
show parameter streams_pool_size;

你应当看到:

  • enable_goldengate_replication = TRUE
  • streams_pool_size 为非 0,当前推荐起点是 3G

准备 XStream 连接用户

XStream 连接用户除了要拿到 XStream 管理权限,通常也需要具备常规 CDC 读取权限。为了避免“参数没问题但联调时仍报权限不足”,建议一次性按已验证权限集授予。

如果你已经有现成 CDC 用户,可以复用;如果没有,就先创建一个专用用户,例如:

create user RTS_RAC_CDC identified by <password>;
grant create session to RTS_RAC_CDC;
grant create table to RTS_RAC_CDC;
grant create sequence to RTS_RAC_CDC;
alter user RTS_RAC_CDC quota unlimited on users;

grant select any transaction to RTS_RAC_CDC;
grant select any table to RTS_RAC_CDC;
grant select any dictionary to RTS_RAC_CDC;
grant flashback any table to RTS_RAC_CDC;
grant logmining to RTS_RAC_CDC;
grant execute_catalog_role to RTS_RAC_CDC;
grant select_catalog_role to RTS_RAC_CDC;
grant analyze any to RTS_RAC_CDC;

grant execute on dbms_logmnr to RTS_RAC_CDC;
grant execute on dbms_logmnr_d to RTS_RAC_CDC;
grant execute on dbms_xstream_adm to RTS_RAC_CDC;
grant execute on dbms_xstream_auth to RTS_RAC_CDC;

grant select on v_$database to RTS_RAC_CDC;
grant select on v_$archived_log to RTS_RAC_CDC;
grant select on v_$log to RTS_RAC_CDC;
grant select on v_$logfile to RTS_RAC_CDC;
grant select on v_$log_history to RTS_RAC_CDC;
grant select on v_$transaction to RTS_RAC_CDC;
grant select on v_$logmnr_logs to RTS_RAC_CDC;
grant select on v_$logmnr_contents to RTS_RAC_CDC;
grant select on v_$logmnr_parameters to RTS_RAC_CDC;
grant select on v_$logmnr_stats to RTS_RAC_CDC;

说明:

  • 严格来说,数据库侧“创建 outbound server”最小只需要 XStream 管理授权;
  • 如果只授这部分权限,后面很可能还会因为字典视图、建表、LogMiner 相关调用继续报错,因此建议直接按已验证权限集补齐。

授予 XStream 管理权限

给连接用户授予 XStream 管理权限:

begin
dbms_xstream_auth.grant_admin_privilege(
grantee => 'RTS_RAC_CDC',
privilege_type => 'CAPTURE',
grant_select_privileges => true
);
end;
/

执行后,建议核对:

select username, privilege_type, grant_select_privileges
from dba_xstream_administrator
where username = 'RTS_RAC_CDC';

你应当看到:

  • PRIVILEGE_TYPE = CAPTURE
  • GRANT_SELECT_PRIVILEGES = YES

授权说明:

  • 步骤 4 里的 grant create sessiongrant select any tablegrant execute on dbms_xstream_* 等语句,只是在给连接用户补普通登录、读取和包执行权限;
  • 真正把该用户声明为 XStream 管理用户的是这一步的 dbms_xstream_auth.grant_admin_privilege(...),两类授权不能互相替代;
  • grant execute on dbms_xstream_auth to RTS_RAC_CDC; 只表示该用户可以调用这个包,不等于已经拿到了 CAPTURE 管理权限;
  • 这一步应由 SYSDBA 或具备等效管理权限的账号执行,不要切到业务用户或连接用户自己执行;
  • 如果漏掉这一步,后续即使 create_outbound 语句本身能提交,也常会在查询 DBA_XSTREAM_ADMINISTRATOR、绑定 connect_user 或客户端 attach 阶段暴露权限问题。

创建并启动 outbound server

执行:

begin
dbms_xstream_adm.create_outbound(
server_name => 'DBZXOUT',
schema_names => 'TESTUSER'
);

dbms_xstream_adm.alter_outbound(
server_name => 'DBZXOUT',
connect_user => 'RTS_RAC_CDC'
);

dbms_xstream_adm.set_parameter(
streams_name => 'DBZXOUT',
streams_type => 'apply',
parameter => 'max_sga_size',
value => '1024'
);

dbms_xstream_adm.start_outbound(
server_name => 'DBZXOUT'
);
end;
/

说明:

  • server_name 是后续作业里要填写的 debezium.database.out.server.name
  • schema_names 应替换成你实际要同步的业务 schema;
  • connect_user 应替换成你的 XStream 连接用户。

执行后,建议核对:

select server_name, status, capture_name, connect_user
from dba_xstream_outbound
where server_name = 'DBZXOUT';

select capture_name, status, purpose
from dba_capture
where capture_name = 'CAP$_DBZXOUT_1';

联调前你通常会看到:

  • DBA_XSTREAM_OUTBOUND.STATUS = DETACHED
  • DBA_CAPTURE.STATUS = ENABLED

补业务表读取授权

最后,给 XStream 连接用户补业务表读取权限,例如:

grant select on TESTUSER.ORDERS to RTS_RAC_CDC;
grant select on TESTUSER.PRODUCTS to RTS_RAC_CDC;

如果你的业务表不在 TESTUSER 下,就按实际 schema 和表名替换。

提作业前的最终核对

在真正提交 XStream 作业之前,建议至少确认下面三张视图都有预期结果:

  • DBA_XSTREAM_OUTBOUND
  • DBA_CAPTURE
  • DBA_XSTREAM_ADMINISTRATOR

如果这三处都正常,再进入下一小节去检查客户端依赖和 OCI 连接方式。

客户端配置

XStream 的难点通常不在数据库,而在客户端依赖。提交作业前,建议按下面的顺序完成客户端配置。

准备 Java 侧依赖包

flink-udf-lib 添加下面两个 jar:

  • ojdbc8.jar
  • xstreams.jar

获取方式:

  • ojdbc8.jar 应优先从 Oracle 官方 JDBC 下载页获取,或者通过 Oracle 官方提供的 JDBC 制品坐标由 Maven / Gradle 拉取;
  • 如果运行环境本身已经安装了 Oracle 数据库软件或 Oracle Client,也可以优先复用该安装介质中自带的 JDBC 驱动;
  • xstreams.jar 不在 Oracle Instant Client 下载页单独提供,通常应从与目标数据库主版本一致的 Oracle DatabaseOracle Database Client 安装介质中获取;
  • 如果现场已经安装了 Oracle 数据库软件或 Oracle Client,常见路径是 $ORACLE_HOME/rdbms/jlib/xstreams.jar
  • 如果现场还没有可用的 ORACLE_HOME,应通过 Oracle 官方交付渠道下载对应版本安装介质后提取,例如 Oracle Software Delivery Cloud 或企业自己的 Oracle 安装包仓库;
  • ojdbc8.jarxstreams.jar 都不建议从第三方镜像、论坛附件或来源不明的压缩包中获取,否则很容易出现版本不一致、包内容不完整或 license 边界不清的问题。

安装 Oracle Instant Client

除了 Java jar,还必须准备 OCI native 依赖,也就是 Oracle Instant Client。

获取方式:

  • Oracle Instant Client 应从 Oracle 官方下载页获取:https://www.oracle.com/database/technologies/instant-client/downloads.html
  • 选择与你的操作系统、CPU 架构以及目标数据库兼容的版本;
  • 至少下载 BasicBasic Light 包,Oracle 官方说明这两个包是运行 OCI / JDBC-OCI 应用的基础包;
  • 如果你们公司走商业软件交付流程,也可以从 Oracle Software Delivery Cloud 或内部制品库获取,但仍应保证来源是 Oracle 官方交付件。

安装位置说明:

  • 负责生成 / 提交 / 预检作业的 data-link-proxy,本身会加载 Oracle OCI 相关依赖
  • 负责运行作业的是 Flink 集群,需要装在实际执行 source 的 TaskManager 运行节点或镜像里

一个推荐做法是,把 Instant Client 解压到 NFS 共享目录,例如:

mkdir -p /nfs-data/flink/lib
tmp_dir=$(mktemp -d /nfs-data/flink/lib/.instantclient_unpack.XXXXXX)
unzip instantclient-basic-linux.x64-19*.zip -d "$tmp_dir"
extracted_dir=$(find "$tmp_dir" -maxdepth 1 -type d -name 'instantclient_*' | head -n 1)
mv "$extracted_dir" /nfs-data/flink/lib/instantclient_19c
rmdir "$tmp_dir"
ls -l /nfs-data/flink/lib/instantclient_19c

注意:

  • 如果 /nfs-data/flink/lib/instantclient_19c 已存在,先备份或清理旧目录,再执行上面的 mv
  • 不要在目标目录已存在时直接执行 mv /nfs-data/flink/lib/instantclient_* /nfs-data/flink/lib/instantclient_19c,否则很容易把新解压目录再套进旧目录里,导致实际库文件路径比预期多一层。

安装完成后,至少确认 Instant Client 目录下存在:

  • libclntsh*
  • libocijdbc*

配置 JVM 的 native 库搜索路径

假设共享存储上的目录同样是:

/nfs-data/flink/lib/instantclient_19c

并且容器内统一挂载到:

/opt/flink/lib/instantclient_19c

这里的前提是:你挂载的是 Instant Client 子目录本身,而不是它的父目录。

  • 如果宿主机路径就是 /nfs-data/flink/lib/instantclient_19c,那么容器内 mountPath 也必须直接对应 /opt/flink/lib/instantclient_19c
  • 不要再把这个子目录挂到 /opt/flink/lib,否则 JVM 会去 /opt/flink/lib/instantclient_19c 下找库,但实际文件会落在 /opt/flink/lib 根目录,路径会错一层。
  1. data-link-proxy 配置共享存储目录下的 Instant Client
env:
- name: JAVA_TOOL_OPTIONS
value: "-Djava.library.path=/opt/flink/lib/instantclient_19c"
- name: LD_LIBRARY_PATH
value: "/opt/flink/lib/instantclient_19c"
volumeMounts:
- mountPath: /opt/flink/lib/instantclient_19c
name: flink-lib-volume
volumes:
- name: flink-lib-volume
hostPath:
path: /nfs-data/flink/lib/instantclient_19c
type: DirectoryOrCreate
  1. Flink 集群配置共享存储目录下的 Instant Client
# jobmanager / taskmanager deployment
env:
- name: LD_LIBRARY_PATH
value: "/opt/flink/lib/instantclient_19c"
volumeMounts:
- mountPath: /opt/flink/lib/instantclient_19c
name: flink-lib
volumes:
- name: flink-lib
hostPath:
path: /nfs-data/flink/lib/instantclient_19c
type: DirectoryOrCreate

# flink config.yaml
env.java.opts.all: '-Djava.library.path=/opt/flink/lib/instantclient_19c'
classloader.parent-first-patterns.additional: "oracle.;oracle.jdbc.;oracle.sql.;oracle.net.;com.oracle."

补充说明:

  • 上面这组示例只覆盖 Instant Client native 库目录的挂载与 JVM 路径配置;
  • ojdbc8.jarxstreams.jar 仍然需要单独存放在实时同步链路的共享目录 /nfs-data/flink/lib/,并通过 Flink / 应用可见的 lib 目录或 classpath 加载,不能因为挂了 /opt/flink/lib/instantclient_19c 就省略,也不要把它们放进 instantclient_19c 子目录。

作业侧推荐配置

单机 XStream 的最小模板如下:

source:
type: oracle
jdbc.url: jdbc:oracle:oci:@//<host>:<port>/<service>
username: <xstream_user>
password: <xstream_password>
database: <db_name>
tables: <db_name>.<schema>.<table>
debezium.database.connection.adapter: xstream
debezium.database.out.server.name: <outbound_server>
debezium.oracle.version: 11

RAC 集群配置

RAC Oracle 使用 LogMiner

数据库侧前置

RAC + LogMiner 相比单机,额外建议先确认下面几项:

  • cluster_database = TRUE
  • remote_listener 已指向 SCAN
  • gv$instance 能看到所有实例均为 OPEN
  • 数据库当前为 ARCHIVELOG

执行口径说明:

  • 以下数据库侧步骤只需在任一实例上以 sysdba 执行一次,无需在每个 instance 上重复执行;
  • 这些操作作用于同一个 RAC 数据库,而不是“每个实例各自维护一套独立库对象”;
  • 需要按集群视角补做的是执行后的结果核对,例如 gv$instancev$databaseSCAN / VIP 连通性,而不是重复做建用户、授权、开日志。

数据库侧执行顺序,仍然沿用单机 LogMiner

  1. 开启 FORCE LOGGING
  2. 开启数据库级 supplemental logging
  3. 创建 CDC 用户并补齐 LogMiner 所需权限
  4. 对业务表开启表级 supplemental log data (all) columns
  5. 给 CDC 用户授予业务表读取权限

连接方式

RAC + LogMiner 推荐按下面的优先级理解连接入口:

  • 集群内 / 内网联调:优先使用 SCAN + Service Name
  • 定点排障:可直接连某个节点 VIP

作业侧推荐配置

当前 Non-CDB + RAC + LogMiner 场景,可以直接从单机场景平移为 SCAN 入口,例如:

source:
type: oracle
jdbc.url: jdbc:oracle:thin:@//<scan-host>:1521/<service>
username: <cdc_user>
password: <cdc_password>
database: <db_name>
tables: <db_name>.<schema>.<table>
scan.startup.mode: initial
debezium.database.connection.adapter: logminer

RAC Oracle 使用 XStream

数据库侧前置

RAC + XStream 在单机 XStream 基础上,数据库侧额外注意两点:

  1. RAC 参数要按集群口径生效:
alter system set enable_goldengate_replication=true scope=both sid='*';
alter system set streams_pool_size=3G scope=both sid='*';
  1. 后续若要让 attach 更稳定,建议为 XStream 单独准备 dedicated service,而不是复用泛化 ORCL19

数据库侧其余步骤,仍沿用单机 XStream

  • 创建 / 复用连接用户
  • 补齐 LogMiner + XStream 权限
  • dbms_xstream_auth.grant_admin_privilege(...)
  • dbms_xstream_adm.create_outbound(...)
  • dbms_xstream_adm.alter_outbound(...)
  • dbms_xstream_adm.start_outbound(...)

连接方式与实例归属

这是 RAC + XStream 最关键的差异点。当前推荐口径是走 dedicated service。

dedicated service 配置思路

若你们的 RACAdmin-Managed,可参考当前已验证通过的做法:

export ORACLE_HOME=/u01/app/oracle/product/19.0.0/dbhome_1
export PATH=$ORACLE_HOME/bin:$PATH

srvctl add service \
-db ORCL19 \
-service ORCL19_XSTREAM \
-preferred ORCL191 \
-available ORCL192 \
-policy AUTOMATIC \
-clbgoal LONG \
-rlbgoal NONE \
-notification TRUE \
-failback YES

srvctl start service -db ORCL19 -service ORCL19_XSTREAM

创建 service 后,建议再补一条:

begin
dbms_capture_adm.set_parameter(
capture_name => 'CAP$_DBZXOUT_1',
parameter => 'use_rac_service',
value => 'Y');
end;
/

这样做的目标不是“新增一个普通 service”,而是让 XStream + RAC 的客户端入口与 queue owner 实例归属保持一致。

客户端配置

RAC + XStream 的客户端配置,仍然沿用第二章单机 XStream 的规则:

  • data-link-proxyJobManager、所有 TaskManager 都要能看到同一套 Oracle 客户端依赖
  • ojdbc8.jarxstreams.jar、Instant Client 主版本保持一致
  • JAVA_TOOL_OPTIONS / env.java.opts.allLD_LIBRARY_PATH 指向 Instant Client 目录
  • jdbc.url 必须使用 jdbc:oracle:oci

作业侧推荐配置

当前 Non-CDB + RAC + XStream 场景,推荐最小模板如下:

source:
type: oracle
jdbc.url: jdbc:oracle:oci:@//<scan-host>:1521/ORCL19_XSTREAM
username: <xstream_user>
password: <xstream_password>
database: <db_name>
tables: <db_name>.<schema>.<table>
debezium.database.connection.adapter: xstream
debezium.database.out.server.name: DBZXOUT
debezium.oracle.version: 11

说明:

  • 默认接入方式是 dedicated service,不再推荐继续使用泛化 ORCL19

参数优化

Redo Group

  • RAC 中每个实例有自己的 redo thread,避免多个实例争用同一组 redo log
  • RAC 每个实例至少需要 2 组 redo log。你现在每个 thread 3 组,满足最低要求。
  • redo group 推荐 multiplex,也就是每组至少 2 个 member。因为 LGWR 会并发写同组所有 member,如果某个 member 坏了还能继续;如果一个 group 的所有 member 都不可写,实例会出问题。
  • RAC 各 thread 的 redo group 数量、大小、member 数应保持一致,便于切换、归档和故障处理。
  • 常规经验目标:高峰期单个 thread 大约 15-30 分钟切一次比较舒服;

生产推荐

每个 thread:6 组 online redo
每组:2G 或 4G
每组:2 members

常见问题

LOG_MINING_FLUSHORA-00947: not enough values

常见表现:

  • LogMiner 初始化或 flush 阶段失败
  • 报错里出现 INSERT INTO LOG_MINING_FLUSH VALUES (0)
  • 同时伴随 ORA-00947

常见原因:

  • 手工创建的 LOG_MINING_FLUSH 结构不符合当前 connector 预期
  • 该表被误建成多列,而不是单列结构

处理建议:

  • 常规 Non-CDB 场景下,优先让 connector 自动创建 LOG_MINING_FLUSH
  • 如果必须手工创建,结构应为:
CREATE TABLE LOG_MINING_FLUSH (
LAST_SCN NUMBER(19,0)
);

(来源:knowledge/facts/knowledge-base/oracle19c-rac-logminer-cdc-setup.md

ORA-01031: 权限不足

常见表现:

  • 读取字典、查询动态视图、初始化 capture 或 attach XStream 时失败
  • LogMinerXStream 场景都可能出现

常见原因:

  • CDC 用户缺少 DBMS_LOGMNR* 包执行权限
  • 缺少 v_$databasev_$logmnr_*v_$archived_log 等动态视图读取权限
  • XStream 场景下,还可能缺少 DBMS_XSTREAM_* 包权限或管理授权

处理建议:

  • 先按文档中的最小权限集补齐
  • 如果仍报错,根据失败 SQL 再补精确授权
  • XStream 场景下,不要只授 execute on dbms_xstream_auth,还要执行:
begin
dbms_xstream_auth.grant_admin_privilege(
grantee => '<xstream_user>',
privilege_type => 'CAPTURE',
grant_select_privileges => true
);
end;
/

UnsatisfiedLinkError: no clntshno ocijdbc19

常见表现:

  • XStream 作业启动失败
  • JVM 找不到 Oracle OCI native 库
  • 日志中出现 no clntshno ocijdbc19 in java.library.path

常见原因:

  • 没有安装 Oracle Instant Client
  • LD_LIBRARY_PATHjava.library.path 未指向 Instant Client 目录
  • ojdbc8.jarxstreams.jar 与 Instant Client 主版本不一致

处理建议:

  • 确认 Instant Client 目录下存在 libclntsh*libocijdbc*
  • 确认 LD_LIBRARY_PATHJAVA_TOOL_OPTIONS / env.java.opts.all 指向正确目录
  • 对齐 ojdbc8.jarxstreams.jar 与 Instant Client 主版本

SQLFeatureNotSupportedException: getOCIHandles

常见表现:

  • XStream 配置看起来都已补齐
  • 但 attach 时直接失败
  • 报错包含 getOCIHandles

常见原因:

  • XStream 连接误用了 jdbc:oracle:thin
  • 而不是 jdbc:oracle:oci

处理建议:

  • adapter=xstream 时,必须使用:
jdbc:oracle:oci:@//<host>:<port>/<service>
  • 如果是 thin,请直接改成 oci

Failed to resolve Oracle database versionInternal Error: Fetch error message failed!

常见表现:

  • data-link-proxy 侧已经看不到 no ocijdbc19
  • 但作业运行时仍然报 Oracle OCI/JDBC 建连异常

常见原因:

  • Oracle 客户端运行时条件还没完全满足
  • 常见根因包括:
  • jar 与 Instant Client 版本混用
  • 节点缺少 libaio.so.1
  • java.library.path 已生效,但实际加载到的 Oracle 运行栈仍不完整

处理建议:

  • 先确认不是“路径没配上”,而是进入了“运行栈不完整”阶段
  • 重点核对:
  • ojdbc8.jar / xstreams.jar / Instant Client 主版本是否一致
  • 节点是否具备 libaio.so.1
  • Flink 是否重复加载了 Oracle jar
  • classloader.parent-first-patterns.additional 是否保留了 Oracle 包前缀

外网通过 SCAN 访问 RAC 报 ORA-12537: TNS:connection closed

常见表现:

  • 数据库在集群内可用
  • 但外网本地客户端通过 SSH 隧道访问 SCAN 时失败

常见原因:

  • SCAN LISTENER 会把客户端重定向到内网 VIP
  • 外网本地客户端无法接住这次内网重定向

处理建议:

  • 外网临时调试时,不要走 SCAN
  • 改为“SSH 隧道直连某个节点 VIP

RAC + XStreamDBZXOUT=ATTACHED 但增量不推进

常见表现:

  • Oracle 侧看起来已经 ATTACHED
  • captured_scn 长时间不推进
  • gv$xstream_outbound_server.total_messages_sent=0
  • 目标端迟迟没有增量

常见原因:

  • XStream attach 落到了和 queue owner 不一致的实例
  • 这是 RAC + XStream 的典型“静默失败”

处理建议:

  • 不要继续使用泛化 ORCL19 service / SCAN
  • 默认改走 dedicated service,例如 ORCL19_XSTREAM
  • 排障期也可以临时固定到 queue owner 对应实例 VIP

ORA-26812: An active session currently attached to XStream server "DBZXOUT"

常见表现:

  • 新作业提交后直接失败或不断重试
  • 旧作业仍在运行,或旧 session 尚未释放

常见原因:

  • 同一个 outbound server 仍被另一条活跃 XStream 作业占用
  • dedicated service 只能解决“实例路由正确性”,不能消除单 session 边界

处理建议:

  • 同一时刻只保留一条 attach 到同一 DBZXOUT 的活跃作业
  • stop/restart 后确认旧 session 已释放,再拉起新作业
  • 若当前链路还在走 initial + backfill,需同时关注 XStream 与 backfill 的生命周期冲突

结论上,这属于当前 XStream 的运行约束,而不是单纯的瞬时异常。

指标监控

推荐监控的指标如下