准备用 Golang 二次开发一个 MES 系统,需要连接 Oracle 数据库读取数据。 Gorm 官方文档有 Oracle 数据库的连接说明:
It is built on top of the Go Driver for Oracle (Godror)
https://gorm.io/zh_CN/docs/connecting_to_the_database.html#Oracle-Database
而 Godror 则依赖 ODPI-C 和 Oracle Instant Client, 我发现在 Ubuntu 上安装 Oracle Instant Client 没啥参考文档 (官方文档基本都是基于 Oracle Linux 和 Red Hat 的),所以把摸索的过程记录下来,造福宇宙。
为何要安装 Oracle Instant Client
To use ODPI-C with Godror, you’ll need to install the Oracle Instant Client on your system.
即,要使用 Gorm 连接 Oracle 数据库,必须安装 Oracle Instant Client。
ODPI-C 是 Oracle Database Programming Interface for C 的缩写,是一个 C 语言的库,简化了 C/C++ 应用程序访问 Oracle 数据库的过程。它是 Oracle Call Interface (OCI) 的一个封装,使得应用程序和语言接口更容易开发。
Oracle Instant Client 支持 Windows、Linux 和 macOS。
这里以 Ubuntu 20.04 为例,介绍安装步骤。更高版本的 Ubuntu 也类似。
下载 oracle instant client ZIP 包
因为 Ubuntu 上不能使用 rpm 包安装,所以直接下载 zip 包解压使用。(那些 rpm 包是针对 Oracle Linux 的)
https://www.oracle.com/database/technologies/instant-client/linux-x86-64-downloads.html
版本选择: 下载与你的 Oracle 数据库版本一致或更高的客户端版本(例如,连接 19c 数据库建议使用 19c 或更高版本的客户端)。
glibc 版本确认
确认当前 Ubuntu 系统的 glibc 版本。
$ ldd --version
ldd (Ubuntu GLIBC 2.31-0ubuntu9.2) 2.31
Copyright (C) 2020 Free Software Foundation, Inc.
我选择了 19.29 版本的 instant client,因为它支持的最低 glibc 版本是 2.17,符合要求。 新版本 glibc 可以运行为旧版本 glibc 编译的程序。
解压 instant client
sudo mkdir -p /opt/oracle
cd /opt/oracle
sudo unzip instantclient-basic-linux.x64-19.29.0.0.0dbru.zip
确认解压后的目录名,例如 instantclient_19_29
$ ls instantclient_19_29
BASIC_LICENSE libccme_base.so libclntsh.so.10.1 libclntshcore.so.19.1 libocci.so libocci.so.19.1 liboramysql19.so uidrvci
BASIC_README libccme_base_non_fips.so libclntsh.so.11.1 libcryptocme.so libocci.so.10.1 libocci_gcc53.so libtfojdbc1.so xstreams.jar
adrci libccme_ecc.so libclntsh.so.12.1 libipc1.so libocci.so.11.1 libocci_gcc53.so.19.1 network
genezi libccme_ecc_non_fips.so libclntsh.so.18.1 libmql1.so libocci.so.12.1 libociei.so ojdbc8.jar
libccme_asym.so libclntsh.so libclntsh.so.19.1 libnnz19.so libocci.so.18.1 libocijdbc19.so ucp.jar
/opt 目录是 Linux 系统中放置第三方软件的常用目录,opt 是 optional 的缩写,表示可选的意思。 删除时也方便,直接删除 /opt/oracle 目录即可。
安装系统依赖
Oracle Instant Client 需要 libaio 库才能运行。根据你的 Ubuntu 版本运行:
sudo apt update
# Ubuntu 22.04 及以前版本
sudo apt install libaio1
# Ubuntu 24.04+ 版本 (可能需要 libaio1t64)
sudo apt install libaio1t64
如果是使用的 instant client 19 版本,还需要安装 libnsl
sudo apt install libnsl-dev
但是报错:
E: Unable to locate package libnsl-dev
我最后也没搞定 libnsl-dev 的安装,不过并没有影响 gorm 读取 oracle 数据库 😅
配置动态链接库
配置动态链接库,让系统可以找到 Oracle Instant Client 的库文件
sudo sh -c "echo /opt/oracle/instantclient_19_29 > /etc/ld.so.conf.d/oracle-instantclient.conf"
sudo ldconfig
注意:将路径替换为你实际的解压路径。
另外一种方式是设置环境变量 LD_LIBRARY_PATH。这里不记录怎么配置了,我只用了第一种方式。
golang 代码
import (
"github.com/oracle-samples/gorm-oracle/oracle"
"gorm.io/gorm"
)
dataSourceName := `user="test" password="test"
connectString="dbhost:1521/orclpdb1"`
db, err := gorm.Open(oracle.Open(dataSourceName), &gorm.Config{})
测试读取一个表
为了防止意外,我创建了一个测试用的只读权限的 Oracle 用户,参考 (Oracle 创建只读用户)
var items []map[string]interface{}
db.Raw("SELECT * FROM another_user.some_table").Scan(&items)
log.Println("Items from Oracle some_table:", items)
哈哈,果然测试成功了。✌
需要注意的是,如果你连接的是用户 A,但表属于用户 B,你需要显式指定 Schema:
- 错误做法: SELECT * FROM some_table(如果当前用户不是所有者)。
- 正确做法: SELECT * FROM another_user.some_table(加上所有者前缀)。
否则会报错:
dpiStmt_execute: ORA-00942: table or view does not exist
CGO 问题
godror 里的说明:
Important: because this is a CGO enabled package, you are required to set the environment variable CGO_ENABLED=1 and have a gcc compile present within your path.
因为 CGO_ENABLED 默认是 1,所以一般不需要设置这个环境变量。
只是要注意,不要手动把 CGO_ENABLED 设为 0。
参考
- https://odpi-c.readthedocs.io/en/latest/user_guide/installation.html#oracle-instant-client-zip-files
关于作者 🌱
我是来自山东烟台的一名开发者,有感兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊,或者关注我的个人公众号“大象工具”, 查看更多联系方式