R odbc无法找到已存在的Oracle驱动的问题排查求助
R连接Oracle ODBC的问题排查与求助
问题初始现象
在RStudio及sudo运行的R中执行以下代码时报错:
> odbc::dbConnect(odbc::odbc(), driver = "/opt/oracle/instantclient_23_4/libsqora.so.23.1") Error: nanodbc/nanodbc.cpp:1138: 00000 [unixODBC][Driver Manager]Can't open lib '/opt/oracle/instantclient_23_4/libsqora.so.23.1' : file not found
使用isql连接DSN时返回:
[28000][unixODBC][Oracle][ODBC][Ora]ORA-01017: invalid username/password; logon denied
初步怀疑问题出在R的odbc包上。
环境信息
- R会话信息:
R version 4.4.0 (2024-04-24) Platform: x86_64-pc-linux-gnu Running under: Ubuntu 22.04.4 LTS other attached packages: [1] odbc_1.4.2 DBI_1.2.2
libsqora权限设置为777:
ls -l /opt/oracle/instantclient_23_4/libsqora.so.23.1 -rwxrwxrwx 1 rdpdp rdpdp 802848 Apr 25 01:38 /opt/oracle/instantclient_23_4/libsqora.so.23.1
- unixODBC版本:
odbcinst --version unixODBC 2.3.9
诊断过程(编辑补充)
通过system命令诊断,终端运行R后执行system("isql -v test asdf asdf")返回:
[01000][unixODBC][Driver Manager]Can't open lib '/opt/oracle/instantclient_23_4/libsqora.so.23.1' : file not found [ISQL]ERROR: Could not SQLConnect
用ldd检查依赖发现两个库未找到:
system('ldd /opt/oracle/instantclient_23_4/libsqora.so.23.1') linux-vdso.so.1 (0x00007fff1a9bc000) /opt/datadog/apm/inject/launcher.preload.so (0x0000798d847fb000) libdl.so.2 => /usr/lib/x86_64-linux-gnu/libdl.so.2 (0x0000798d847f6000) libm.so.6 => /usr/lib/x86_64-linux-gnu/libm.so.6 (0x0000798d8470f000) libpthread.so.0 => /usr/lib/x86_64-linux-gnu/libpthread.so.0 (0x0000798d8470a000) librt.so.1 => /usr/lib/x86_64-linux-gnu/librt.so.1 (0x0000798d84705000) libaio.so.1 => /usr/lib/x86_64-linux-gnu/libaio.so.1 (0x0000798d846fe000) libresolv.so.2 => /usr/lib/x86_64-linux-gnu/libresolv.so.2 (0x0000798d846ea000) libclntsh.so.23.1 => not found libclntshcore.so.23.1 => not found libodbcinst.so.2 => /usr/lib/x86_64-linux-gnu/libodbcinst.so.2 (0x0000798d846c1000) libc.so.6 => /usr/lib/x86_64-linux-gnu/libc.so.6 (0x0000798d84400000) /lib64/ld-linux-x86-64.so.2 (0x0000798d848be000) libltdl.so.7 => /usr/lib/x86_64-linux-gnu/libltdl.so.7 (0x0000798d846b4000)
原因是LD_LIBRARY_PATH未包含Oracle客户端目录:
system("echo $LD_LIBRARY_PATH") /usr/lib/R/lib:/usr/lib/x86_64-linux-gnu:/usr/lib/jvm/default-java/lib/server
执行Sys.setenv(LD_LIBRARY_PATH="/opt/oracle/instantclient_23_4")后,system("isql -v test asdf asdf")返回:
[28000][unixODBC][Oracle][ODBC][Ora]ORA-01017: invalid username/password; logon denied [ISQL]ERROR: Could not SQLConnect
说明R的shell环境依赖问题已解决,但odbc包仍无法连接,怀疑是odbc识别的LD_LIBRARY_PATH存在问题。
后续排查(2024年5月20日补充)
发现system("isql -v ...")必须将Oracle客户端目录放在LD_LIBRARY_PATH首位才能正常运行:
Sys.setenv(LD_LIBRARY_PATH=paste0("/opt/oracle/instantclient_23_4", ':', '/lib64/', ':', Sys.getenv('LD_LIBRARY_PATH')))
而将Oracle目录追加到路径末尾则无效:
Sys.setenv(LD_LIBRARY_PATH=paste0(Sys.getenv('LD_LIBRARY_PATH'), ':', "/opt/oracle/instantclient_23_4", ':', '/lib64/'))
尝试重新编译安装odbc包:
withr::with_makevars(c(PKG_LIBS="-L/opt/oracle/instantclient_23_4/ -L/lib64/"), install.packages("odbc"), assignment="+")
但无效果。手动加载依赖库后出现新错误:
dyn.load("/opt/oracle/instantclient_23_4/libclntsh.so.23.1") dyn.load("/opt/oracle/instantclient_23_4/libclntshcore.so.23.1") dyn.load("/opt/oracle/instantclient_23_4/libnnz.so") > DBI::dbConnect(odbc::odbc(), 'test', pwd = 'asdf') Error: nanodbc/nanodbc.cpp:1138: 00000 [unixODBC][Driver Manager]Driver's SQLAllocHandle on SQL_HANDLE_HENV failed
现寻求解决该问题的方法。
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

