oracle_fdw 使用手册
1 概述
oracle_fdw 用于让 UDB 通过 Oracle Client(OCI)访问 Oracle 数据库,并把 Oracle 的表(或查询结果)映射为 UDB 内可查询的外部表。
1.1 适用范围与选型建议
当目标数据源为 Oracle,优先使用
oracle_fdw;相比通用 ODBC 方案,专用 FDW 通常在类型映射、谓词下推、执行计划展示等方面更可控。oracle_fdw依赖 Oracle Client/Instant Client 的运行时环境;外部访问由 UDB 服务进程发起,因此环境变量必须对服务进程生效。
1.2 工作链路
SQL 查询
→ UDB 服务进程
→ oracle_fdw
→ Oracle Client(OCI / Instant Client)
→ Oracle 服务器
交付包通常已包含 oracle_fdw 扩展文件;正常情况下无需额外准备,只需在 ud_sql 中创建扩展、创建外部服务器与外表即可使用。若连接失败,再参考本文“连接失败排查”。
2 快速开始
2.1 前提
UDB 服务已启动,
ud_sql可正常进入(例如unvdb=#)。目标 Oracle 可访问(网络可达、账号具备权限)。
Oracle 用户至少具备
CREATE SESSION权限,并对目标表/视图具备SELECT权限。
路径约定(示例,按现场替换):
<安装包目录>:UDB 安装/解压目录,例如/home/unvdb/work/UDB-TX-26<数据目录>:UDB 数据目录,例如/home/unvdb/work/unvdb-data环境变量推荐写入:
<数据目录>/env.sh(示例:/home/unvdb/work/unvdb-data/env.sh),并在启动服务前source使其对服务进程生效
2.2 最小可用 SQL(复制后替换占位符)
占位符说明:
<oracle_host>:Oracle 主机地址<oracle_port>:Oracle 监听端口(默认场景常见为 1521,现场以实际为准)<oracle_service>:服务名(service name)<oracle_user>/<oracle_pwd>:Oracle 用户与口令<oracle_table>:要映射的 Oracle 表名(以 Oracle 数据字典为准,常见为大写)<tns_alias>:TNS 别名(使用 tnsnames.ora 时)
建议在执行前先确认三件事:Oracle 的主机/端口/服务名;Oracle 用户是否有权限;目标表是否存在且列结构与下方外表定义匹配。
提示:下面快速开始中的外表列 id/name 仅为示例(用于演示环境的简单表)。实际使用时,请按目标 Oracle 表的列顺序与类型调整外表列定义;不要假设所有目标表都是两列且列名/类型固定。
如何确认 <oracle_service>(service name)与端口:
最简单:向 Oracle DBA 获取一条可用连接串(Easy Connect 或 tnsnames.ora 中的别名)。
如果现场有
tnsnames.ora:直接使用其中的<tns_alias>(见下方 TNS 示例),或从文件中读取HOST/PORT/SERVICE_NAME填入 Easy Connect。如果有权限在 Oracle 上执行 SQL,可查询服务名:
SELECT name FROM v$services;
如何确认目标表列顺序/类型(用于定义外表列):
如果能在 Oracle 上执行 SQL:
SELECT column_id, column_name, data_type FROM all_tab_columns WHERE owner='<oracle_user>' AND table_name='<oracle_table>' ORDER BY column_id;
CREATE EXTENSION IF NOT EXISTS oracle_fdw;
DROP SERVER IF EXISTS oracle_svr CASCADE;
CREATE SERVER oracle_svr
FOREIGN DATA WRAPPER oracle_fdw
OPTIONS (dbserver '//<oracle_host>:<oracle_port>/<oracle_service>');
DROP USER MAPPING IF EXISTS FOR CURRENT_USER SERVER oracle_svr;
CREATE USER MAPPING FOR CURRENT_USER
SERVER oracle_svr
OPTIONS (user '<oracle_user>', password '<oracle_pwd>');
DROP FOREIGN TABLE IF EXISTS ft_oracle_demo;
CREATE FOREIGN TABLE ft_oracle_demo (
id numeric,
name text
)
SERVER oracle_svr
OPTIONS (schema '<oracle_user>', table '<oracle_table>');
SELECT * FROM ft_oracle_demo;
要点:
dbserver推荐使用 Easy Connect://host:port/service(port 常见为 1521,现场以实际为准)客户现场如已维护 tnsnames.ora,也可使用 TNS 别名方式:
OPTIONS (dbserver '<tns_alias>'),并在<数据目录>/env.sh中设置TNS_ADMIN指向 tnsnames.ora 所在目录外表列需与 Oracle 侧列类型兼容;首次验证建议先选简单表或只映射少量列
schema通常为 Oracle 用户名;table名称以 Oracle 数据字典为准(常见为大写)
示例(TNS 别名方式):
DROP SERVER IF EXISTS oracle_svr CASCADE;
CREATE SERVER oracle_svr
FOREIGN DATA WRAPPER oracle_fdw
OPTIONS (dbserver '<tns_alias>');
export TNS_ADMIN=<tnsnames.ora所在目录>
3 常见用法
3.1 映射 Oracle 表
CREATE FOREIGN TABLE ft_t1 (
id numeric OPTIONS (key 'true'),
name text
)
SERVER oracle_svr
OPTIONS (schema '<oracle_user>', table 'T1');
说明:
这是 oracle_fdw 的限制:对外表执行 UPDATE/DELETE 时,至少需要一列标记为主键列(
OPTIONS (key 'true')),否则会报错 “no primary key column specified for foreign Oracle table”与“快速开始”的区别:快速开始的外表示例主要用于验证 SELECT 跑通;若你还希望对 Oracle 端数据执行 UPDATE/DELETE,需要像本节这样在外表列上标记 key(联合主键则每个主键列都要标记)
3.2 映射 Oracle 查询(只读建议)
CREATE FOREIGN TABLE ft_q1 (
id numeric,
name text
)
SERVER oracle_svr
OPTIONS (table '(SELECT id, name FROM T1 WHERE id <= 100)', readonly 'true');
说明:
映射查询时通常不再设置
schema;以table '(SELECT ...)'为准。写入(INSERT/UPDATE/DELETE)仅可能在“简单查询”上工作;复杂查询建议开启
readonly。
4 诊断与运维
4.1 查看诊断信息
SELECT oracle_diag();
用途:查看 oracle_fdw 与 Oracle client 的版本、以及服务进程视角的关键环境信息。
也可传入外部服务器名,额外显示 Oracle server 版本(示例):
SELECT oracle_diag('<foreign_server_name>');
说明:<foreign_server_name> 为你实际创建的 FOREIGN SERVER 名称(例如前文示例为 oracle_svr,现场也可能叫 ora_svr)。
4.2 关闭当前会话缓存连接
SELECT oracle_close_connections();
适用:修改了连接相关环境或希望释放 Oracle 会话资源。
5 连接失败排查(仅当报错时看)
5.1 典型报错:OCIEnvCreate failed
常见原因(按优先级):
Oracle client 库不在服务进程可见的库搜索路径中(
LD_LIBRARY_PATH对服务进程未生效)Instant Client 缺少必要
libclntsh.so*软链接或依赖缺失UDB 与 Oracle client 架构/位数不一致
建议按顺序处理:
在
ud_sql执行SELECT oracle_diag();,核对版本与环境是否符合预期确认“启动 UDB 服务进程之前”已加载环境(例如数据目录的
env.sh);修改后需重启服务使其生效若现场使用自备 Instant Client,确保
libclntsh.so*及依赖库齐全,并按 Oracle 要求创建必要软链接
可直接使用的定位命令:
第 1 步(数据库侧诊断):
SELECT oracle_diag();
第 2 步(确认 env.sh 生效到服务进程):
# 1) 找到 UDB 服务进程 PID(按现场实际进程名调整关键字)
pgrep -af 'unvdbsvr|unvdb'
# 2) 查看该 PID 进程实际继承到的环境变量(以服务进程为准)
PID=<上一步看到的PID>
tr '\0' '\n' < /proc/$PID/environ | egrep '^(LD_LIBRARY_PATH|TNS_ADMIN|ORACLE_HOME)='
# 3) 推荐把环境变量写入 <数据目录>/env.sh(示例:/home/unvdb/work/unvdb-data/env.sh)
grep -nE '^(export )?(LD_LIBRARY_PATH|TNS_ADMIN|ORACLE_HOME)=' <数据目录>/env.sh
说明:
重点看第 2) 的输出:如果服务进程环境里没有
LD_LIBRARY_PATH(或不包含 Oracle client 目录),oracle_fdw 很可能无法加载libclntsh.so*等依赖库。修改
<数据目录>/env.sh后需要先关闭 UDB 服务进程,然后source <数据目录>/env.sh再启动,新的环境变量才会对服务进程生效。
5.2 现场自备 Oracle Client/Instant Client 时的环境变量
以下变量必须在“启动 UDB 服务进程之前”生效:
export LD_LIBRARY_PATH=<instantclient_or_oracle_home_lib>:$LD_LIBRARY_PATH
export TNS_ADMIN=<network_admin_dir>
推荐落地方式(写入 <数据目录>/env.sh 并在启动前加载):
source <数据目录>/env.sh
<数据目录>/start.sh
5.3 依赖库自检
目的:确认交付包中的 Oracle client 运行库齐全、软链接正确、依赖库无缺失,并且对 UDB 服务进程可见。
假设交付包目录为 <安装包目录>(示例:/home/unvdb/work/UDB-TX-26)。
确认 Oracle client 库是否存在(示例路径,按实际替换):
ls -l <安装包目录>/lib/libclntsh.so* <安装包目录>/lib/libociei.so* 2>/dev/null
ls -l <安装包目录>/lib/ | egrep 'libclntsh|libociei|libnnz|libons|libclntshcore' || true
确认软链接是否指向真实文件:
readlink -f <安装包目录>/lib/libclntsh.so
readlink -f <安装包目录>/lib/libociei.so 2>/dev/null
用 ldd 检查依赖是否缺失(出现
not found就是“库缺失或路径未生效”):
ldd <安装包目录>/lib/oracle_fdw.so | egrep 'not found|libclntsh|libociei' || true
ldd <安装包目录>/lib/libclntsh.so* | egrep 'not found' || true
说明:
如果
ldd输出包含not found,通常需要补齐缺失 so,或确保LD_LIBRARY_PATH通过<数据目录>/env.sh在启动前生效。软链接只能解决“库名匹配/SONAME 找得到”,不能替代真实库文件与完整依赖链。