首批通过分布式安全可靠测评,为关键业务系统打造
Linux 版 ODBC 驱动安装与配置
更新时间:2026-07-02 11:25:58
获取到 Linux 版 OceanBase Connector/ODBC 安装包后,根据如下步骤进行安装与配置。
依赖版本要求
- libobclient:V2.1.2
第一步:检查驱动是否安装及驱动版本
检查是否已安装 OceanBase Connector/ODBC,并查看相应版本信息。
rpm -qa | grep odbc
rpm -qa | grep obclient
如已安装,以下为返回内容:
# rpm -qa | grep odbc
ob-connector-odbc-2.0.9.2-20230719101407.el7.alios7.x86_64
ob-unixodbc-2.0.8.3-20231114143843.el7.alios7.x86_64
# rpm -qa | grep obclient
libobclient-2.1.2-20211201104607.el7.alios7.x86_64
如果需要替换其他版本,执行如下命令先删除软件包。
# rpm -ev ob-unixodbc
# rpm -ev ob-connector-odbc
# rpm -ev libobclient
如未安装,请参见下面章节,首先安装软件依赖包,再安装 ODBC 驱动。
第二步:安装软件依赖包
你需要安装软件依赖包 Libtool 的两个工具:libtool-ltdl 和 libreadline。
安装 libtool-ltdl
执行下面的命令,检查是否已安装 libtool-ltdl。
rpm -qa | grep libtool-ltdl如果已安装,返回结果示例如下:
libtool-ltdl-2.4.2-22.el7_3.x86_64如未安装,执行下面的命令安装。
sudo yum search libtool-ltdl sudo yum install libtool-ltdl
安装 libreadline
执行下面的命令,检查是否已安装 libreadline。
rpm -qa|grep readline如果已安装,返回结果示例如下:
readline-6.2-9.1.alios7.x86_64如未安装,请执行下面的命令安装。
sudo yum search readline sudo yum install readline安装后再次检查文件是否存在。
ls -lth /usr/lib64/libreadline.so.6如果
/usr/lib64/libreadline.so.6文件不存在,执行下面的命令创建软连接。# rpm -qa|grep readline readline-8.0-3.ky10.x86_64 # rpm -ql readline-8.0-3.ky10.x86_64 /usr/lib64/libhistory.so.7 /usr/lib64/libhistory.so.7.0 /usr/lib64/libhistory.so.8 /usr/lib64/libhistory.so.8.0 /usr/lib64/libreadline.so.7 /usr/lib64/libreadline.so.7.0 /usr/lib64/libreadline.so.8 /usr/lib64/libreadline.so.8.0 /usr/share/licenses/readline /usr/share/licenses/readline/COPYING /usr/share/licenses/readline/USAGE # ln -s /usr/lib64/libreadline.so.8 /usr/lib64/libreadline.so.6 # ls -lth /usr/lib64/libreadline.so.6 lrwxrwxrwx 1 root root 27 Jan 3 14:56 /usr/lib64/libreadline.so.6 -> /usr/lib64/libreadline.so.8
第三步:安装 OceanBase ODBC 驱动
完成安装软件依赖包 Libtool 后,你可以依次执行下面的命令安装 ODBC 驱动。
sudo rpm -ivh libobclient-<version_no>.rpm
sudo rpm -ivh ob-connector-odbc-<version_no>.rpm
sudo rpm -ivh ob-unixodbc-<version_no>.rpm
安装完成后,再次分别执行下面的命令检查安装情况和版本。
rpm -qa | grep odbc
rpm -qa | grep obclient
如已安装,返回结果示例如下:
# rpm -qa | grep odbc
ob-connector-odbc-2.0.9.2-20230719101407.el7.alios7.x86_64
ob-unixodbc-2.0.9.2-20230719100704.el7.alios7.x86_64
# rpm -qa | grep obclient
libobclient-2.2.0-20221017150844.el7.alios7.x86_64
第四步:配置文件
配置 odbc.ini
配置 odbc.ini 到 /etc/odbc.ini(也可以自定义目录设置环境变量到相应的目录即可),执行下面的命令,编辑 odbc.ini 配置文件。
sudo vim /etc/odbc.ini
执行上面的命令后,即可见配置文件,配置文件内的内容和释义如下:
[ODBC Data Sources]
data_source_name = OBDSN
[OBDSN]
Driver=Oceanbase
Description = OceanBase Driver DSN
SERVER = 10.10.20.20
PORT = 2883
USER = ALVIN@oboracle#obcluster
Password = xxx
Database = ALVIN
OPTION = 4
charset=UTF8
[OBDSNMYSQL]
Driver=Oceanbase
Description = OceanBase Driver DSN
SERVER = xxx.xxx.xxx.xxx
PORT = 10003
USER = tester@sys
Password = 1******
Database = unittests
OPTION = 4
charset=UTF8
[OBDSNMULTIHOST]
Driver=Oceanbase
Description = OceanBase Driver DSN with Multi-IP Support
MULTIHOST = 1
SERVER = xxx.xxx.xxx.xxx:38882,xxx.xxx.xxx.xxx:38884
USER = tester@sys
配置文件中的参数含义和取值约束如下表所示。
| 参数名称 | 含义 |
|---|---|
| Driver | odbcinst.ini 中的驱动,是用户自定义的。 |
| Description | 驱动描述。 |
| SERVER | 数据库 IP 地址。支持多 IP 配置,多个 IP 地址用逗号分隔,例如:xxx.xxx.xxx.xxx:38882,xxx.xxx.xxx.xxx:38884。 |
| PORT | 数据库实际端口。 |
| MULTIHOST | 多 IP 配置开关。设置为 1 开启多 IP 功能,0 关闭(默认)。 |
| USER | 数据库用户账号。 |
| Password | 数据库密码。 |
| Database | 数据库名称。 |
| OPTION | 配置选项(开启日志,OPTION=4)。 |
| charset | 数据库字符集,默认为 UTF8。 |
配置 odbcinst.ini
配置 odbcinst.ini 到 /etc/odbcinst.ini(也可以自定义目录设置环境变量到相应的目录即可)。执行下面的命令,编辑 odbcinst.ini 配置文件。
sudo vim /etc/odbcinst.ini
点击键盘上的 i 进入编辑状态,将下面的内容添加到文件内。需要注意的是,[Oceanbase]前面不能有空格。
[Oceanbase]
Description = ODBC for Oceanbase
Driver = /u01/ob-connector-odbc/lib64/mariadb/libobodbc.so
最后,点击键盘上的 esc,输入 :wq 保存并退出文件。
第五步:设置环境变量。
临时添加环境变量
通过该方式添加的环境变量仅对当前终端会话有效,在退出终端会话后就会失效。
$export ODBCSYSINI=/etc
$export ODBCINI=/etc/odbc.ini
$export LD_LIBRARY_PATH=/u01/unix-odbc/lib:/u01/obclient/lib:/u01/ob-connector-odbc/lib64/mariadb:$LD_LIBRARY_PATH
为当前用户永久添加环境变量
通过该方式添加的环境变量,在退出终端会话后,添加的环境变量对当前用户仍然生效。
vim ~/.bashrc
编辑 .bashrc 文件,在文件结尾处添加以下信息:
export ODBCSYSINI=/etc
export ODBCINI=/etc/odbc.ini
export LD_LIBRARY_PATH=/u01/unix-odbc/lib:/u01/obclient/lib:/u01/ob-connector-odbc/lib64/mariadb:$LD_LIBRARY_PATH
保存修改并退出文件,再执行以下命令使配置生效。
source ~/.bashrc
为所有用户永久添加环境变量
通过该方式添加的环境变量,在退出终端会话后,添加的环境变量对所有用户仍然生效。
vim /etc/profile
编辑 /etc/profile 文件,在文件结尾处添加以下信息:
export ODBCSYSINI=/etc
export ODBCINI=/etc/odbc.ini
export LD_LIBRARY_PATH=/u01/unix-odbc/lib:/u01/obclient/lib:/u01/ob-connector-odbc/lib64/mariadb:$LD_LIBRARY_PATH
保存修改并退出文件,再执行以下命令使配置生效。
source /etc/profile
第六步:检查环境变量配置情况
环境变量配置完成后,使用 odbcinst -j 命令查看配置是否正确:
/u01/unix-odbc/bin/odbcinst -j
返回结果示例如下:
unixODBC 2.3.0
DRIVERS............: /etc/odbcinst.ini
SYSTEM DATA SOURCES: /etc/odbc.ini
FILE DATA SOURCES..: /etc/ODBCDataSources
USER DATA SOURCES..: /etc/odbc.ini
SQLULEN Size.......: 8
SQLLEN Size........: 8
SQLSETPOSIROW Size.: 8
第七步:检查环境依赖是否正确
执行下面的命令,检查环境依赖是否正确,确保 libobclnt.so.20 的依赖与所安装的 libobclient-xxx.rpm 包对应。
执行下面的命令切换到 ODBC 连接器库文件所在目录:
cd /u01/ob-connector-odbc/lib64/mariadb
使用 ldd 命令来列举 libobodbc.so 的依赖关系:
ldd /u01/ob-connector-odbc/lib64/mariadb/libobodbc.so
返回结果示例如下:
linux-vdso.so.1 => (0x00007ffe4d3fc000)
libobclnt.so.20 => /u01/obclient/lib/libobclnt.so.20 (0x00007f063217c000)
libodbcinst.so.2 => /u01/unix-odbc/lib/libodbcinst.so.2 (0x00007f0631f64000)
libm.so.6 => /lib64/libm.so.6 (0x00007f0631c62000)
libc.so.6 => /lib64/libc.so.6 (0x00007f0631894000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007f0631690000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f0631474000)
libltdl.so.7 => /lib64/libltdl.so.7 (0x00007f063126a000)
/lib64/ld-linux-x86-64.so.2 (0x00007f0632675000)
第八步:测试连接
ISQL 连接测试
DriverManager 相关的工具在 /u01/unix-odbc 目录下,运行连接命令并显示成功。
/u01/unix-odbc/bin/isql -v OBDSN
预期运行结果如下所示:
+-------------------------------+
| Connected! |
| |
| sql-statement |
| help [tablename] |
| quit |
| |
+-------------------------------+
SQL>
(可选)第九步:编译 C++ 测试程序
本章节将以 C++ 通过 OceanBase Connector/ODBC 进行创建表、插入数据、查询和删除数据的为例,展示如何编译 C++ 测试程序。
使用下面的命令创建 test.cpp 文件。
vim test.cpp
下面的文件内容提供了配置示例,您只需将示例中的 DSN=OBDSN 替换为您的实际 DSN 名称。以下是本文 /etc/odbc.ini 文件中的 OBDSN 示例:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sql.h"
#include "sqlext.h"
typedef struct tagODBCHandler {
SQLHENV henv;
SQLHDBC hdbc;
SQLHSTMT hstmt;
}ODBCHandler;
int IS_SUCC(SQLRETURN retcode) {
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) return 1;
return 0;
}
void checkError(SQLRETURN retcode, const char* msg, ODBCHandler* handler) {
SQLCHAR message[SQL_MAX_MESSAGE_LENGTH + 1];
SQLCHAR sqlstate[SQL_SQLSTATE_SIZE + 1];
SQLINTEGER error;
SQLSMALLINT len;
SQLRETURN tmpcode;
switch (retcode){
case SQL_SUCCESS:
printf("%s retcode is SQLRETURN\n", msg);
break;
case SQL_SUCCESS_WITH_INFO:
printf("%s retcode is SQL_SUCCESS_WITH_INFO\n", msg);
break;
case SQL_ERROR:
printf("%s retcode is SQL_ERROR\n", msg);
tmpcode = SQLError(handler->henv, handler->hdbc, handler->hstmt, sqlstate, &error, message, sizeof(message), &len);
if (tmpcode != SQL_SUCCESS && tmpcode != SQL_SUCCESS_WITH_INFO) {
printf("get sqlerror failed %d", tmpcode);
} else {
printf("error is %d, meeesage is %s, sqlstate is %s, len is %d\n", error, message, sqlstate, len);
}
break;
case SQL_INVALID_HANDLE:
printf("%s retcode is SQL_INVALID_HANDLE\n", msg);
break;
case SQL_STILL_EXECUTING:
printf("%s retcode is SQL_STILL_EXECUTING\n", msg);
break;
case SQL_NO_DATA:
printf("%s retcode is SQL_NO_DATA\n", msg);
break;
default:
printf("%s retcode is UNKNOWN retcode\n", msg);
break;
}
}
int main(int argc, char** argv) {
ODBCHandler handler;
SQLRETURN retcode;
#define MAX_NAME_LEN 255
SQLCHAR connOut[MAX_NAME_LEN+1];
SQLSMALLINT len;
//Allocate environment handle
retcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &handler.henv);
// Set the ODBC version environment attribute
if (!IS_SUCC(retcode)) {
checkError(retcode, "SQLAllocHandle", &handler);
return -1;
}
retcode = SQLSetEnvAttr(handler.henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3_80, 0);
// Allocate connection handle
if (!IS_SUCC(retcode)) {
checkError(retcode, "SQLSetEnvAttr", &handler);
return -1;
}
retcode = SQLAllocHandle(SQL_HANDLE_DBC, handler.henv, &handler.hdbc);
if (!IS_SUCC(retcode)) {
checkError(retcode, "SQLAllocHandle", &handler);
return -1;
}
// Set login timeout to 5 seconds
SQLSetConnectAttr(handler.hdbc, SQL_LOGIN_TIMEOUT, (SQLPOINTER)5, 0);
// Connect to data source
retcode = SQLDriverConnect(handler.hdbc, NULL, (SQLCHAR*)"DSN=OBDSN", SQL_NTS, connOut, MAX_NAME_LEN, &len,SQL_DRIVER_NOPROMPT);
if (!IS_SUCC(retcode)) {
checkError(retcode, "SQLDriverConnect", &handler);
return -1;
}
retcode = SQLAllocHandle(SQL_HANDLE_STMT, handler.hdbc, &handler.hstmt);
if (!IS_SUCC(retcode)) {
checkError(retcode, "SQLAllocHandle", &handler);
return -1;
}
{
//drop
SQLExecDirect(handler.hstmt, (SQLCHAR*)"drop table PERSON", SQL_NTS);
SQLFreeStmt(handler.hstmt, SQL_CLOSE);
}
{
//create
retcode = SQLExecDirect(handler.hstmt, (SQLCHAR*)"create table PERSON(id int, num int, name varchar2(100))", SQL_NTS);
if (!IS_SUCC(retcode)) {
checkError(retcode, "SQLExecDirect", &handler);
return -1;
}
SQLFreeStmt(handler.hstmt, SQL_CLOSE);
}
{
//insert
retcode = SQLPrepare(handler.hstmt, (SQLCHAR*)"insert into PERSON values(?,?,'test')", SQL_NTS);
if (!IS_SUCC(retcode)) {
checkError(retcode, "SQLPrepare", &handler);
return -1;
}
SQLINTEGER id = 0;
SQLINTEGER num = 0;
retcode = SQLBindParameter(handler.hstmt, 1, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, &id, 0, NULL);
if (!IS_SUCC(retcode)) {
checkError(retcode, "SQLBindParameter", &handler);
return -1;
}
retcode = SQLBindParameter(handler.hstmt, 2, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, &num, 0, NULL);
if (!IS_SUCC(retcode)) {
checkError(retcode, "SQLBindParameter", &handler);
return -1;
}
retcode = SQLExecute(handler.hstmt);
if (!IS_SUCC(retcode)) {
checkError(retcode, "SQLExecute", &handler);
return -1;
}
SQLFreeStmt(handler.hstmt, SQL_CLOSE);
}
{
//update
SQLINTEGER id = 0;
retcode = SQLPrepare(handler.hstmt, (SQLCHAR*)"update PERSON set num=2, name='hello' where id=?", SQL_NTS);
if (!IS_SUCC(retcode)) {
checkError(retcode, "SQLPrepare", &handler);
return -1;
}
retcode = SQLBindParameter(handler.hstmt, 1, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, &id, 0, NULL);
if (!IS_SUCC(retcode)) {
checkError(retcode, "SQLBindParameter", &handler);
return -1;
}
retcode = SQLExecute(handler.hstmt);
if (!IS_SUCC(retcode)) {
checkError(retcode, "SQLExecute", &handler);
return -1;
}
SQLFreeStmt(handler.hstmt, SQL_CLOSE);
}
{
//select
retcode = SQLPrepare(handler.hstmt, (SQLCHAR*)"select * from PERSON", SQL_NTS);
if (!IS_SUCC(retcode)) {
checkError(retcode, "SQLPrepare", &handler);
return -1;
}
retcode = SQLExecute(handler.hstmt);
if (!IS_SUCC(retcode)) {
checkError(retcode, "SQLExecute", &handler);
return -1;
}
SQLINTEGER id = 0;
SQLINTEGER num = 0;
char name[100] = { 0 };
retcode = SQLBindCol(handler.hstmt, 1, SQL_INTEGER, &id, sizeof(id), NULL);
if (!IS_SUCC(retcode)) {
checkError(retcode, "SQLBindCol", &handler);
return -1;
}
retcode = SQLBindCol(handler.hstmt, 2, SQL_INTEGER, &num, sizeof(num), NULL);
if (!IS_SUCC(retcode)) {
checkError(retcode, "SQLBindCol", &handler);
return -1;
}
retcode = SQLBindCol(handler.hstmt, 3, SQL_CHAR, name, sizeof(name), NULL);
if (!IS_SUCC(retcode)) {
checkError(retcode, "SQLBindCol", &handler);
return -1;
}
retcode = SQLFetch(handler.hstmt);
if (!IS_SUCC(retcode)) {
checkError(retcode, "SQLFetch", &handler);
return -1;
}
SQLFreeStmt(handler.hstmt, SQL_CLOSE);
printf("id=%d, num=%d, name=%s", id, num, name);
}
{
//delete
SQLINTEGER id = 0;
retcode = SQLPrepare(handler.hstmt, (SQLCHAR*)"delete from PERSON where id=?", SQL_NTS);
if (!IS_SUCC(retcode)) {
checkError(retcode, "SQLPrepare", &handler);
return -1;
}
retcode = SQLBindParameter(handler.hstmt, 1, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, &id, 0, NULL);
if (!IS_SUCC(retcode)) {
checkError(retcode, "SQLBindParameter", &handler);
return -1;
}
retcode = SQLExecute(handler.hstmt);
if (!IS_SUCC(retcode)) {
checkError(retcode, "SQLExecute", &handler);
return -1;
}
SQLFreeStmt(handler.hstmt, SQL_CLOSE);
}
// clean handle
SQLFreeHandle(SQL_HANDLE_STMT, handler.hstmt);
SQLDisconnect(handler.hdbc);
SQLFreeHandle(SQL_HANDLE_DBC, handler.hdbc);
SQLFreeHandle(SQL_HANDLE_ENV, handler.henv);
return 0;
}
通过如下命令测试:
g++ -I /u01/unix-odbc/include/ test.cpp -L/u01/ob-connector-odbc/lib64/mariadb -lobodbc -o test
./test
预期运行结果如下所示:
#./test
id=0, num=2, name=hello