1. ODBC对应的驱动包
机器信息
IP | 主机名 | 系统 | 角色 |
---|---|---|---|
172.16.3.20 | yuna-0001 | openEuler 20.03 64bit with ARM | 主服务器 |
172.16.3.22 | yuna-0003 | openEuler 20.03 64bit with ARM | 备服务器 |
172.16.3.23 | yuna-0004 | openEuler 20.03 64bit with ARM | 客户端 |
odbc安装包
官网下载odbc包后解压至指定位置
例:
/gauss/software/目录下
解压后odbc路径:
/gauss/software/odbc/lib/****
(默认已安装好数据库集群)
2. 配置ODBC环境
客户端:
1)查看unixODBC是否安装
在非root用户,查看系统unixODBC是否安装
方法(例如centos环境):
yum list unixODBC*
主要是查看unixODBC和unixODBC-devel这两个程序是否被安装,如果没有安装则安装之,如果yum找不到安装源,则更新yum源(网上有很多更新yum源的资料,此处不详细说明)
2)查看odbc配置文件目录
- 查看odbc.ini
odbc_config --odbcini
如下,不同的环境可能odbc用的odbc.ini目录不一样。
文档的测试环境中odbc找的是/etc/odbc.ini。
- 查看odbcinst.ini
执行odbc_config --odbcinstini查看odbcinst.ini目录。
如下,不同的环境可能odbc用的odbcinst.ini目录不一样。
文档的测试环境中odbc找的是/etc/odbcinst.ini。
3. 修改ODBC链接属性参数
ODBC链接属性参数分为两部分:
①odbc.ini为链接数据库的链接参数配置文件
关键配置参数有:
[dsn_name] //指定odbc链接的dsn数据源名称
Driver = openGauss //指定odbcinst.ini里的[section]
Database = dbname //指定odbc链接的数据库名
Servername = host_ip_1,host_ip_2,.. //指定odbc多host地址链接的主备多ip地址
Username = user_test //指定odbc链接的用户名
Password = test_1234 //指定odbc链接用户对应的密码
Port = port_test //指定odbc链接数据库主备机的端口
debug = 1
[ODBC]
Trace = yes
TraceFile = /tmp/trace.log
注:正常客户环境,主备都是在不同机器上搭建的,所以是多ip,同一port,所以在odbc.ini里的Servername配置多个ip地址,用逗号分隔。
[ODBC]数据源下面的配置是方便链接失败时分析使用。为固定写法。
②odbcinst.ini为配置odbc所查找使用的驱动程序
写[section]名称,且要与odbc.ini里的Driver对应。
比如odbc.ini里的Driver = openGauss, 则odbcinst.ini里应该对应为[openGauss]。
即如下示例:
[openGauss]
Driver64 = /gauss/software/odbc/lib/psqlodbcw.so
Setup64 = /gauss/software/odbc/lib/psqlodbcw.so
FileUsage = 1
测试odbc.ini和odbcinst.ini文件是否成功
方法:
用系统unixODBC自带的isql测试配置参数是否能链接成功。
isql -v dsn_name
文档测试环境中odbc.ini的dsn配置为gauss,所以测试成功示例如下:
注:
如果测试失败,则查看最新的/tmp/mylog_isql_userxxxxx.log日志。里面有“connecting to the database using URL: postgres://xxxx”
查看URL后面的链接字符串。检测链接串中的user:pasword@ip1:port1,ip2:port2,…,多ip和端口/dbname?target_session_attrs=read-write,配置参数是否与odbc.ini一致。
如果链接成功,会有“libpq connection to the database established.”显示。
4. ODBC测试程序
测试程序说明:
测试程序需要在odbc.ini指定的用户下创建表test结构。
create table test(id int, name name);
测试程序中,进行了对表test的写数据,读数据操作,并在读写数据执行前,进行sleep,暂停1秒,且会无限循环的对表test进行读写操作。方便人为的进行switchover,failover,主库halt -f三种场景的测试操作。
#include
#include
#include
#include
#include
#include
#include
#define NAME_LEN 255
#define TRUE 1
#define FALSE 0
//程序执行前提,要有一张表test(id int, name name)
//写入的数据
SQLSMALLINT ID = 12;
SQLCHAR NAME[NAME_LEN] = "test_name";
SQLBIGINT len_ID = 0, len_NAME = SQL_NTS;
SQLCHAR OutConnStr[255];
SQLSMALLINT OutConnStrLen;
SQLHENV henv = SQL_NULL_HENV; // Environment
SQLHDBC hdbc = SQL_NULL_HDBC; // Connection handle
SQLHSTMT hstmt = SQL_NULL_HSTMT; // Statement handle
SQLRETURN retcode;
void connection_dsn(SQLHENV *henv, SQLHDBC *hdbc){
printf("ODBC connect... \n");
retcode = SQLAllocHandle(SQL_HANDLE_DBC, *henv, hdbc);
retcode = SQLSetConnectAttr(*hdbc, SQL_LOGIN_TIMEOUT, (SQLPOINTER)5, 0);
retcode = SQLDriverConnect(*hdbc, NULL, "DSN=gauss;", SQL_NTS, OutConnStr, 255, &OutConnStrLen, SQL_DRIVER_COMPLETE);
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {
printf("ODBC connect success! \n");
}else {
printf("ODBC connect failed! \n");
}
}
int main () {
long int second = 0;
//无限循环执行,即出需要ctrl + c
while(1) {
retcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
retcode = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER*)SQL_OV_ODBC3, 0);
connection_dsn(&henv, &hdbc);
re_execute:
sleep(1); //睡眠1秒,方便人为进行switchover,failover,主库halt -f三种场景的测试
second++;
printf("Executing %ld s. \n", second);
retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
retcode = SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_SSHORT, SQL_INTEGER, 0, 0, &ID, 0, &len_ID);
retcode = SQLBindParameter(hstmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, NAME_LEN, 0, NAME, 0, &len_NAME);
retcode = SQLPrepare(hstmt, (SQLCHAR*)"INSERT INTO test (ID, NAME) VALUES (?, ?)", SQL_NTS);
retcode = SQLExecute(hstmt);
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {
printf("ODBC insert into test data successed! \n");
}else {
printf("ODBC insert into test data failed! \n");
connection_dsn(&henv, &hdbc);
printf("Again execute write data operation! \n");
goto re_execute;
}
retcode = SQLFreeStmt(hstmt, SQL_CLOSE);
re_fetch:
sleep(1); //睡眠1秒,方便人为进行switchover,failover,主库halt -f三种场景的测试
second++;
printf("Executing %ld s. \n", second);
retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
retcode = SQLExecDirect(hstmt, (SQLCHAR *)"SELECT * FROM test", SQL_NTS);
retcode = SQLFetch(hstmt);
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {
printf("ODBC select * from test data successed! \n");
}else {
printf("ODBC select * from test data failed! \n");
connection_dsn(&henv, &hdbc);
printf("Again execute read data operation! \n");
goto re_fetch;
}
printf("Output the table test data: \n");
while(retcode == SQL_SUCCESS||retcode == SQL_SUCCESS_WITH_INFO) {
memset(NAME, ' ', NAME_LEN);
retcode = SQLGetData(hstmt, 1, SQL_INTEGER, &ID, 0, NULL);
retcode = SQLGetData(hstmt, 2, SQL_C_CHAR, NAME, NAME_LEN, &len_NAME);
printf ("\n ID : %i", (int)ID);
printf ("\n Name : %.10s", NAME);
retcode = SQLFetch(hstmt);
}
if (hstmt != SQL_NULL_HSTMT) {
SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
}
if (hdbc != SQL_NULL_HDBC) {
SQLDisconnect(hdbc);
SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
}
if (henv != SQL_NULL_HENV) {
SQLFreeHandle(SQL_HANDLE_ENV, henv);
}
}
printf ("\nComplete.\n");
return 0;
}
5. odbc测试程序编译与运行
编译前提是系统上装有gcc编译工具。
- 编译方法:
gcc -g -o 执行程序文件名 测试程序文件名 -l odbc - 示例:
gcc -g -o test odbc_test.c -l odbc //测试程序为odbc_test.c,执行程序为test
- 运行odbc测试程序:
./可执行程序文件名
示例: ./test //编译的可执行文件为test
执行示例:
6. 验证odbc测试程序写数据操作
用系统unixODBC自带的isql进行验证测试:
isql -v dsn
isql -v gauss
进入目标主库后,查询表test。
select * from test;
文档测试环境中,dsn配置在odbc.ini中[gauss]
示例如下:
该结果是在循环写读6次后ctrl + c掉测试程序后。如果isql的查询与刚才测试程序读取数据打印结果数量一致,则odbc测试写数据成功。