这是我从 RStudio(和 R,使用 sudo 运行)收到的错误:
> 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
使用 DSN 运行
isql
会导致:
[28000][unixODBC][Oracle][ODBC][Ora]ORA-01017: invalid username/password; logon denied
那么问题可能出在
R
odbc
包上?
会议信息:
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 4月25日01:38 /opt/oracle/instantclient_23_4/libsqora.so.23.1
和:
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
这是因为:
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)
即两个文件没有链接,因为:
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
Help: https://docs.oracle.com/error-help/db/ora-01017/
[ISQL]ERROR: Could not SQLConnect
这意味着现在它已经固定在shell
R
中运行了。不幸的是odbc
仍然无法连接。所以我怀疑这与odbc
认为的LD_LIBRARY_PATH
有关。
--- 2024 年 5 月 20 日编辑 ---
有趣的是,对于
system("isql -v ...")
,oracle
客户端安装文件夹需要位于路径的第一个位置。即:
Sys.setenv(LD_LIBRARY_PATH=paste0("/opt/oracle/instantclient_23_4", ':', '/lib64/', ':', Sys.getenv('LD_LIBRARY_PATH')))
有效,但是:
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
会导致不同的错误:
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
我花了几天的时间才将 Oracle 即时客户端安装到 Docker 容器中并与 R 连接。我不认为我的任何挣扎都是专门针对 R 的,但我不记得所有细节。我可以在这里分享 Dockerfile,以防它有用。
也许答案就在这些 Dockerfile 命令中。
另外两个想法
您是否使用 Oracle 即时客户端安装附带的
.ini
脚本来安装 odbc_update_ini.sh
文件?这个脚本有点棘手,你必须给它一些具体的参数。请参阅注释 # writes odbc ini file
下的命令作为示例。
odbc::odbcListDrivers()
是调试 odbc 连接时运行的有用函数。
FROM rocker/shiny-verse
# system
RUN apt-get update
RUN apt-get install -y unixodbc alien libaio1
# oracle driver installations:
# https://www.oracle.com/database/technologies/instant-client/linux-x86-64-downloads.html#ic_x64_inst
# https://www.oracle.com/database/technologies/releasenote-odbc-ic.html
# paths
RUN sh -c 'echo /usr/lib/oracle/21/client64/lib/ > /etc/ld.so.conf.d/oracle.conf'
RUN ldconfig
# install instant client basic lite
# this is a prerequisite for the odbc driver
# to install an rpm file on Ubuntu, need alien
RUN wget https://download.oracle.com/otn_software/linux/instantclient/2110000/oracle-instantclient-basiclite-21.10.0.0.0-1.el8.x86_64.rpm
RUN alien -i oracle-instantclient-basiclite-21.10.0.0.0-1.el8.x86_64.rpm
# install instant client odbc
RUN wget https://download.oracle.com/otn_software/linux/instantclient/2110000/oracle-instantclient-odbc-21.10.0.0.0-1.el8.x86_64.rpm
RUN alien -i oracle-instantclient-odbc-21.10.0.0.0-1.el8.x86_64.rpm
RUN export PATH=/usr/lib/oracle/21/client64/bin:$PATH
# writes odbc ini file
RUN /usr/lib/oracle/21/client64/bin/odbc_update_ini.sh "/" "/usr/lib/oracle/21/client64/lib" "oracle"
# test in R
RUN R -e 'install.packages("odbc")'
CMD R -e '\
library(odbc); \
library(DBI); \
con <- dbConnect(odbc(), Driver = "oracle", DBQ = "xxx&yy.com:1521/appsdv", \
UID = "myid", PWD = "mypd", Port = 1521); \
con |> dbListTables(schema_name = "MYSCHEMA") |> print()'