odbc_fdw 使用手册

1 概述

odbc_fdw 用于让 UDB 通过 ODBC 访问外部数据源,并把外部表映射为 UDB 内可查询的外部表。

本文示例:以 “UDB 作为外部数据源” 举例(UDB ODBC Driver + 远端 UDB)。

1.1 适用范围与选型建议

  • 当目标数据源已有成熟专用 FDW(例如 MySQL/Oracle 等),优先评估与使用专用 FDW(例如 mysql_fdw/oracle_fdw),ODBC 方案通常用于兼容性接入。

  • ODBC 方案对不同数据源的兼容程度,取决于对应数据源的 ODBC Driver 能力与行为;配置项与可用特性可能存在差异。

1.2 概念与术语

  • unixODBC(Driver Manager,驱动管理器):负责读取 odbcinst.ini/odbc.ini,加载 ODBC Driver,并转发 ODBC 调用。

  • ODBC Driver(目标数据源的 ODBC 驱动):不同数据源的驱动不同;在 Linux 上通常表现为驱动库文件(.so)及其依赖库。

  • 驱动库文件(.so):ODBC Driver 在 Linux 下的落地形态之一,路径通常填写在 odbcinst.iniDriver64 中。

  • 驱动注册文件 odbcinst.ini:把“驱动名”映射到驱动库文件路径(.so)。

  • DSN(Data Source Name,数据源名):odbc.ini 的节名(例如 [REMOTE_UNVDB]);UDB 侧 CREATE SERVER ... OPTIONS (dsn 'REMOTE_UNVDB') 通过 DSN 引用它。

  • DSN 配置文件 odbc.ini:定义数据源名(DSN)及连接参数;UDB 侧 CREATE SERVER ... OPTIONS (dsn '...') 通过 DSN 引用它。

1.3 工作链路

SQL 查询
  → UDB 服务进程
    → odbc_fdw
      → unixODBC(Driver Manager,驱动管理器)
        → ODBC Driver(目标数据源的 ODBC 驱动)
          → 远端数据源

2 路径替换说明

文中 <安装包目录><数据目录> 均为占位符,读者需替换为自己实际路径。

常见示例(仅示意):

  • 安装包目录:例如 /home/unvdb/work/UDB-TX-26-ALL

  • 数据目录:例如 /home/unvdb/work/unvdb-data

3 配置编写:准备驱动、odbcinst.ini、odbc.ini

3.1 准备 ODBC Driver(按目标数据源选择)

odbc_fdw 通过 ODBC 访问外部数据源时,必须先准备“目标数据源对应的 ODBC Driver”(驱动库 .so 及其依赖库)。

常见数据源的驱动获取方式不同:

  • UDB:驱动由交付物提供(见下文 3.1.1)

  • 其他数据源:应获取对应厂商/发行版提供的 ODBC Driver,并按其文档完成安装与注册

3.1.1 示例:使用交付物自带的 UDB ODBC Driver(zip 交付,需解压)

交付物中 UDB ODBC Driver 通常位于:

  • <安装包目录>/Interface/ODBC/

常见驱动包文件名(以实际交付物为准):

  • unvdb_odbc_centos_amd64.zip

  • unvdb_odbc_centos_aarch64.zip

一般 x86_64 机器使用 amd64,aarch64 机器使用 aarch64

解压建议:把驱动与其依赖库解压到 <安装包目录>/lib/,便于与交付包其它库一起由 LD_LIBRARY_PATH 管理。

在继续之前,建议确认 <安装包目录>/lib/ 中已包含 unixODBC 运行库(以实际交付为准):

  • libodbc.so.2

  • libodbcinst.so.2

unzip <安装包目录>/Interface/ODBC/unvdb_odbc_centos_amd64.zip -d <安装包目录>/lib/

解压后通常可见(以实际包内为准):

  • 驱动:unvdbodbcw.sounvdbodbca.so

  • 依赖:libpq.so.5libssl.so.10libcrypto.so.10

下文统一用 <ODBC驱动目录> 指代驱动所在目录,默认即 <安装包目录>/lib/

常见提示与处理建议(zip 解压场景):

  • 解压过程中可能遇到类似提示:目标目录已存在同名文件(例如 libpq.so.5 已存在且为软链接),unzip 会询问是否覆盖。

  • 处理原则:不要盲目覆盖。优先选择不覆盖(输入 n),先完成部署并验证可用性;如后续确需替换,再在明确版本与依赖关系后进行调整。

3.1.2 示例:其他数据源的 ODBC Driver 获取方式(非 UDB)

不同数据源的 ODBC Driver 获取方式不同,常见两类如下:

方式 A:通过系统包管理器安装(示例,仅示意,包名以发行版仓库为准)

sudo yum install -y mysql-connector-odbc

说明:

  • 系统安装后驱动库通常位于系统目录(例如 /usr/lib64/

  • 仍需在 odbcinst.ini 注册驱动条目,并在 odbc.ini 配置 DSN

以 MySQL 为例,安装后常见驱动库文件为:

  • Unicode:/usr/lib64/libmyodbc9w.so

  • ANSI:/usr/lib64/libmyodbc9a.so

查看安装到哪些文件(推荐):

rpm -ql mysql-connector-odbc | egrep 'libmyodbc|README|odbc' | sort

方式 B:手工获取驱动并放置到固定目录(示例)

  • 将驱动库文件(.so)复制到 <安装包目录>/lib/(或系统标准库目录)

  • 若放在 <安装包目录>/lib/,通常可复用既有 LD_LIBRARY_PATH 配置

3.2 编写 odbcinst.ini(注册驱动)

<数据目录>/odbc/odbcinst.ini 增加(按实际路径替换):

[UNVDB]
Description = ODBC Driver for UDB
Driver64    = <ODBC驱动目录>/unvdbodbcw.so
FileUsage   = 1

说明:

  • [UNVDB] 是驱动名;DSN 里通过 Driver = UNVDB 引用,必须一致

  • 默认推荐使用 unvdbodbcw.so(Unicode/Wide);除非明确需要兼容旧调用链,否则不建议选 unvdbodbca.so

  • 不建议通过“随意建立软链接”伪装缺失库;应补齐匹配版本的库文件,或统一选择“交付包自带”或“系统安装”的一套库

3.3 编写 odbc.ini(配置 DSN)

<数据目录>/odbc/odbc.ini 增加(按实际参数替换):

[REMOTE_UNVDB]
Driver      = UNVDB
Description = Remote UDB via ODBC
Database    = unvdb
Servername  = 127.0.0.1
Port        = 5678
UserName    = unvdb

重要说明:

  • 上述 DSN 字段为 “UDB ODBC Driver” 的示例。不同 ODBC Driver 支持的 DSN 参数名可能不同,应以对应驱动文档/示例为准。

  • 常见误配置(供排障参考):某些数据源(例如 MySQL)的 ODBC Driver 同时支持 Socket(本机 Unix Socket)与 Server/Port(TCP),两者属于不同连接方式,不应同时配置,应二选一。

安全建议:

  • 不建议在 odbc.ini 明文写 Password

  • 口令优先在 UDB 内通过 USER MAPPING 配置(见第 5 章“数据库操作”)

4 暴露配置:env.sh(UDB 与 ud_sql 启动前都要 source)

关键点:odbc_fdw 由 UDB 服务进程执行外部访问,因此 ODBCSYSINI/ODBCINI/LD_LIBRARY_PATH 必须在启动服务进程之前就生效;仅在 ud_sql 前设置通常不足以让已启动的服务进程生效。

推荐把环境变量写进 <数据目录>/env.sh,并在启动服务进程与运行 ud_sql 前都 source 一次。

说明:

  • 如果你把目标数据源的 ODBC Driver(以及依赖库)放在 <安装包目录>/lib/,且现场 env.sh 原本就已把 <安装包目录>/lib/ 加入 LD_LIBRARY_PATH,通常不需要为了 odbc_fdw 额外改动 LD_LIBRARY_PATH

  • ODBCSYSINI/ODBCINI 用于让 unixODBC 找到 odbcinst.ini/odbc.ini,通常是启用 odbc_fdw 后新增需要设置的环境变量。

示例(读者替换为自己的实际路径):

export LD_LIBRARY_PATH=<安装包目录>/lib:${LD_LIBRARY_PATH:-}
export ODBCSYSINI=<数据目录>/odbc
export ODBCINI=<数据目录>/odbc/odbc.ini

使用方式:

source <数据目录>/env.sh

说明:

  • 若你修改了 env.sh 或 DSN 配置,需重启 UDB 服务进程使其生效

5 数据库操作(示例:连接外部 UDB)

本章示例目标:在本地 UDB 中创建外部表,查询到外部 UDB 中的表数据。

前置:

  • 已按第 3~4 章完成 ODBC Driver 准备/安装、odbcinst.iniodbc.inienv.sh

  • 启动 UDB 服务进程前、以及运行 ud_sql 前都执行:source <数据目录>/env.sh

ud_sql 中执行(按实际 DSN/账号/表名替换):

CREATE EXTENSION IF NOT EXISTS odbc_fdw;

DROP SERVER IF EXISTS odbc_svr CASCADE;
CREATE SERVER odbc_svr FOREIGN DATA WRAPPER odbc_fdw OPTIONS (dsn 'REMOTE_UNVDB');

CREATE USER MAPPING FOR CURRENT_USER SERVER odbc_svr
OPTIONS (odbc_UID 'unvdb', odbc_PWD '******');

DROP FOREIGN TABLE IF EXISTS ft_test_demo;
CREATE FOREIGN TABLE ft_test_demo (
  id int,
  username text
) SERVER odbc_svr OPTIONS (schema 'public', table 'test_demo');

SELECT * FROM ft_test_demo ORDER BY id;

说明:

  • CREATE SERVER ... OPTIONS (dsn '...')dsn 固定引用 odbc.ini 的 DSN 名;同一个 odbc_fdw 也可通过不同 DSN 连接不同数据源。

  • CREATE USER MAPPING ... OPTIONS (odbc_UID '...', odbc_PWD '...') 属于连接属性;不同数据源账号口令、认证方式以对应 ODBC Driver 支持为准。

  • CREATE FOREIGN TABLE ... OPTIONS (...) 中的选项含义与“目标数据源”相关:

    • 对 UDB(本示例):常用 schema + table

    • 对 MySQL:通常只写 table;目标库名建议写在 DSN(odbc.iniDatabase = ...)中

MySQL 示例(仅示意,参数按实际替换):

DROP SERVER IF EXISTS mysql_svr CASCADE;
CREATE SERVER mysql_svr FOREIGN DATA WRAPPER odbc_fdw OPTIONS (dsn 'MYSQL_DSN');
CREATE USER MAPPING FOR CURRENT_USER SERVER mysql_svr OPTIONS (odbc_UID 'demo_user', odbc_PWD '******');

DROP FOREIGN TABLE IF EXISTS ft_mysql;
CREATE FOREIGN TABLE ft_mysql (
  id int,
  name text
) SERVER mysql_svr OPTIONS (table 't1');

限制说明:

  • 当前版本 odbc_fdw 外部表为只读,不支持 INSERT/UPDATE/DELETE。对外部表执行写入会报错,例如:ERROR: cannot insert into foreign table ...

6 常见错误排查:Connecting to driver 与证据采集

6.1 推荐排障顺序

1)确认 <数据目录>/env.sh 已包含 ODBCSYSINI/ODBCINI,且在启动服务进程前已 source 并重启服务进程
2)确认 ODBC Driver 已就绪(例如驱动库文件 .so 位于 <安装包目录>/lib/ 或系统目录),且 odbcinst.iniDriver64 指向实际 .so
3)采集 UDB 日志(见 6.2)
4)开启 unixODBC trace(见 6.3)并复现报错

6.2 采集 UDB 日志(在 ud_sql 内执行)

定位日志位置:

SHOW logging_collector;
SHOW log_directory;
SHOW log_filename;

如需快速确认日志相关配置:

SELECT name, setting, unit
FROM pg_settings
WHERE name LIKE 'log\_%' ESCAPE '\'
   OR name = 'logging_collector'
ORDER BY name;

6.3 启用 unixODBC trace(定位 Driver Manager/驱动侧错误)

<数据目录>/odbc/odbc.ini 的对应 DSN 节增加(示例):

[REMOTE_UNVDB]
Trace = Yes
TraceFile = <数据目录>/odbc/trace/unixodbc.trace

注意:

  • 需要保证 TraceFile 目录存在且 UDB 服务用户有写权限

  • trace 文件可能增长很快,排障后应关闭

6.4 常见原因速查

  • Driver64 路径错误:odbcinst.ini 指向的 .so 不存在或权限不可读

  • 依赖库缺失:unvdbodbcw.so 依赖的 libpq/libssl/libcrypto 不在动态库搜索路径

  • 服务进程未读到 ini:UDB 服务进程环境里缺 ODBCSYSINI/ODBCINI(仅 ud_sql 设置无效)

  • DSN/驱动名不一致:odbc.iniDriver = ...odbcinst.ini 的段名不一致

  • 多套库混用:系统与交付包同名库被混合加载导致异常

7 安全建议

  • 生产环境使用最小权限账号访问远端

  • 避免在 odbc.ini 明文写口令;口令优先放到 USER MAPPING

  • 限制 odbc.ini/odbcinst.ini 文件权限,确保仅 UDB 服务用户可读