Ubuntu 安装 Oracle Instant Client, 并测试 Golang Gorm 读取 Oracle 数据库

文章目录

    准备用 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 的),所以把摸索的过程记录下来,造福宇宙。

    ⚠️:注意,Gorm 这个方案,并不支持 Oracle 11g 分页处理,所以如果想使用这个方案,请确保 oracle 版本 > 12。如果是 11g 版本,请参考我另一篇笔记: Oracle 11g 的 Golang GORM 分页兼容解决方案

    为何要安装 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 聊聊,或者关注我的个人公众号“大象工具”, 查看更多联系方式