南大通用GBase 8a MPP Cluster开发接口之ODBC篇

原文链接:https://www.gbase.cn/community/post/4307
更多精彩内容尽在南大通用GBase技术社区,南大通用致力于成为用户最信赖的数据库产品供应商。

ODBC 概述

1.1 ODBC 简介

ODBC(开放数据库互连)为客户端程序提供了一种通用的接口来存取数据库。ODBC 是标准化的 API,允许到 SQL 数据库服务器的连接。它根据 SQL AccessGroup 的说明书开发,并定义了一系列的函数调用,错误代码和数据类型,这些可以用来开发独立于数据库的应用程序。ODBC 经常被用在当要求独立于数据库或同步访问不同的数据源时。

ODBC 是应用程序广泛使用的数据库访问接口。它是基于对数据库 APIs 的X/Open 和 ISO/IEC 标准的分级调用接口(CLI)规范,并且使用结构化查询语句(SQL)作为它的数据库访问语言。

ODBC 支持的 ODBC 函数说明在 ODBC API 参考手册中给出。关于 ODBC 一般和更多信息,请参考微软公司网站的相关内容。

1.2 ODBC 驱动管理器

ODBC 驱动管理器是管理 ODBC 应用和驱动程序之间的通信的库。它的主要功能包括:

  • 解析数据源名字(DSN)
  • 装载和卸载驱动程序
  • 处理 ODBC 函数调用或传递它们到驱动程序

下面的驱动程序管理器经常被使用:

  • Microsoft Windows 的 ODBC 驱动管理器(odbc32.dll)
  • unixODBC Unix 驱动管理器(libodbc.so)
  • iODBC Unix 驱动管理器(libiodbc.so)

1.3 ODBC 驱动管理器安装

windows 操作系统已经集成了 ODBC 驱动管理器。通过“控制面板\管理工具\数据源(ODBC)”可以打开。在 64 位 windows 操作系统中集成了 64 位和 32 位的 ODBC 驱动管理器,64 位客户端应用程序需要调用 64 位的 ODBC 驱动管理器,它位于“C:\Windows\ System32\odbcad32.exe”;32 位的客户端应用程序需要调用 32 位的 ODBC 驱动管理器,它位于C:\Windows \SysWOW64\odbcad32.exe”。

Linux 操作系统需要安装 ODBC 驱动管理器,使用如下命令安装:
# rpm -ivh unixODBC-2.2.14-1.x86_64.rpm
# rpm -ivh unixODBC-devel-2.2.14-1.x86_64.rpm

安装成功后您可以通过如下命令查看 unixODBC 的安装信息:

# odbcinst -j
unixODBC 2.2.14
DRIVERS............: /etc/odbcinst.ini
SYSTEM DATA SOURCES: /etc/odbc.ini
FILE DATA SOURCES..: /etc/ODBCDataSources
USER DATA SOURCES..: /home/gbase/.odbc.ini
SQLULEN Size.......: 8
SQLLEN Size........: 8
SQLSETPOSIROW Size.: 8

2 GBase 8a ODBC 综述

2.1 GBase 8a ODBC 简介

GBase 8a ODBC 是 GBase 数据库的 ODBC 驱动程序,通过 GBase 8a ODBC 驱动可以访问所有 GBase 数据库。GBase 8a ODBC 支持 ODBC 3.5X 一级规范 (全部 API + 2 级特性)。GBase 8a ODBC 支持 SSL 安全连接数据传输。注,如需 ODBC 配置 SSL 安全连接传输,需提前准备好 SSL 的 CA 证书、client客户端秘钥和证书文件,将这些文件存放在 ODBC 数据源服务器上,供 ODBC 配置使用。

2.2 安装文件

我们提供的 ODBC 接口的 rpm 文件(linux 版本)格式如下:gbaseodbc_<product version>_<build version>_< archtecture>.rpm。

例如:gbaseodbc_8.4_1.0_x86_64.rpm。

我们提供的 ODBC 接口的 bin 文件(window 版本)格式如下:GBaseODBC-<product version>-<build version>-<os version and archtecture>.rar

例如:GBaseODBC_8.3.81.53_build53.1_windows_x86.rar

2.3 GBase 8a ODBC 体系结构

GBase 8a ODBC 体系结构是基于五个组件,在下图中所示:

  • 应用

应用是通过调用 ODBC API 实现对 GBase 数据访问的程序。应用使用标准的ODBC 调用与驱动程序管理器通信。应用并不关心数据存储在哪里,如何存储的或者系统如何配置来访问数据。它只需要知道数据源名字(DSN)。不管应用程序如何使用 ODBC,它们有许多共同的操作: 

  •  选择 GBase 服务器并连接它
  •  提交 SQL 语句执行
  •  获得结果(如果有的话)
  • 处理错误
  • 执行或回滚包含在 SQL 语句中的事务
  • 断开到 GBase 服务器的连接

大多数的数据访问工作都是由 SQL 完成的,使用 ODBC 的应用主要任务就是提交 SQL 语句并获得由这些语句产生的结果。

  • 驱动管理器

驱动管理器是一个管理应用与驱动程序之间通信的库。它执行下面的任务:

  • 解析数据源名字(DSN)
  • 驱动程序装载和卸载
  • 处理 ODBC 函数调用或将它们传递给驱动程序
  • GBase 8a ODBC 驱动程序

GBase 8a ODBC 驱动程序是一个实现了 ODBC API 的函数库。它处理 ODBC函数调用,提交对 GBase 服务器的 SQL 请求,并返回结果给应用程序。如果需要,GBase 8a ODBC 驱动程序将修改客户发出的请求以便于使该请求符合 GBase数据库支持的语法。

  • ODBC.INI

ODBC.INI 是 ODBC 配置文件,该文件储存了 GBase 8a ODBC 驱动程序连接服务器和数据库的相关信息。例如:GBase 8a ODBC 驱动程序管理器通过 ODBC.INI中的相关信息来决定装载哪个驱动程序。GBase 8a ODBC 驱动程序基于相对应的DSN,系统使用它来读取连接参数。

  • GBase 服务器

GBase 服务器是数据源。它是一个关系数据库管理系统(RDBMS)。

2.4 支持平台

GBase 8a ODBC 支持以下平台:

  • Windows
  • Linux 操作系统
  • Unix

3 GBase 8a ODBC 高可用功能

3.1 高可用性简介

GBase 8a 为扁平架构集群,考虑到集群的高可用性,当某个节点不可用时,应该把到来的连接请求路由到另外一个可用的节点上。高可用就是来实现这样一个功能。

3.2 高可用性使用方法

使用 GBase 8a ODBC 连接 GBase 8a 数据库有两种方式,分别是:配置并使用数据源名称和使用连接字符串。

在 windows 平台下配置数据源名称时,需要在“服务器名称”一栏中填写GBase 8a 数据库所有节点的 IP 地址,并使用“;”分割符将其分割开来(如下图所示),并选择“连接”选项卡中的“高可用性”选项。GBase 8a ODBC 的集群 IP 自动路由功能就会开启。除非数据库集群的所有节点都不可用,否则 GBase8a ODBC 总会将连接路由到数据库群集中的一个可用的节点上。
 

在 linux 平台上配置数据源名称时,修改 odbc.ini 文件中“SERVER”变量的值为 GBase 8a 数据库所有节点的 IP 地址,使用“;”分割符将其分割,并增加 IP_ROUTE=1 选项。GBase 8a ODBC 的高可用功能就会开启。

[ODBC Data Sources]
test = GBase 8a ODBC

[test]
Driver = GBase 8a ODBC 8.3 Driver
DATABASE = test
DESCRIPTION = GBase 8a ODBC 8.3 Driver test
SERVER = 192.168.7.172;192.168.7.173;192.168.7.174
UID = root
PASSWORD = 1

使用 GBase 8a ODBC 连接字符串时,需要将数据库集群所有节点 IP 列在SERVER=之后的大括号中,并使用“;”分割开,并增加 IP_ROUTE=1;

"DRIVER={GBase 8a ODBC 8.3 Driver};"
"SERVER={192.168.5.65;192.168.5.64};"
"UID=root;PWD=1;DATABASE=test;PORT=5258;IP_ROUTE=1;" 

在 linux 下使用 GBase 8a ODBC 连接字符串连接时需要在 odbcinst.ini 文件中写入如下信息:

[GBase 8a ODBC 8.3 Driver]
Description = GBase 8a ODBC
Driver = /usr/lib/libgsodbc8.so
Setup =
FileUsage =1
Threading =0
DontDLClose =1

4 GBase 8a ODBC 负载均衡功能

4.1 负载均衡简介

GBase 8a ODBC 提供的高可用负载均衡功能是指,GBase 8a ODBC 会将客户端请求的数据库集群连接平均分摊到集群所有可用的节点上。

4.2 负载均衡的使用方法

GBase 8a ODBC 提供两种方式来使用高可用负载均衡。一种是配置数据源,另一种是使用连接字符串。如果通过配置数据源使用 GBase 8a ODBC 的高可用负载均衡,在 windows
平台下需要使用 ODBC 数据源管理器打开 GBase 8a ODBC 的数据源配置界面进行配置。如下图所示:

首先要在“服务器名称”文本框中输入集群所有节点的 IP 地址,IP 地址间使用“;”进行分割;其次要打开“高级”选项,选择“连接”选项卡中的“负载均衡”选项,并指定“集群 ID”的值,“节点检测间隔(秒)”是使用高可用负载均衡所需要的,它的默认值为 60 秒;最后点击“确定”,一个带有高可用负载均衡的 GBase 8a ODBC 数据源就配置好了。

在 Linux 平台下则需要修改 odbcinst.ini 和 odbc.ini 数据源配置文件。通常情况下需要将如下内容添加到/etc/odbcinst.ini和/etc/odbc.ini的文件尾部。

在/etc/odbcinst.ini 文件中加入:

[GBase 8a ODBC 8.3 Driver]
Description = GBase 8a ODBC
Driver = /usr/lib/libgsodbc8.so
FileUsage = 1
threading = 0
DontDLClose = 1

在/etc/odbc.ini 文件中加入:

[test]
Driver = GBase 8a ODBC 8.3 Driver
DATABASE = test
DESCRIPTION = GBase 8a ODBC 8.3 Driver DSN
SERVER = 192.168.111.96;192.168.5.212;192.168.7.174
UID = gbase
PASSWORD = gbase20110531
CONNECTION_BALANCE = 1
GCLUSTER_ID = gcluster
CHECK_INTERVAL = 90

如果通过连接字符串使用 GBase 8a ODBC 的高可用负载均衡,请参考如下示例。

"DRIVER=GBase 8a ODBC 8.3 Driver;UID=gbase;PWD=gbase20110531;"
"SERVER={192.168.111.96;192.168.5.212;192.168.7.174;192.168.7.173};"
"CONNECTION_BALANCE=1;GCLUSTER_ID=gcluster;"
"CHECK_INTERVAL=90;" 

如果在 linux 平台下使用连接字符串,需要在/etc/odbcinst.ini 增加往下内容。

[GBase 8a ODBC 8.3 Driver]
Description = GBase 8a ODBC
Driver = /usr/lib/libgsodbc8.so
FileUsage = 1
threading = 0
DontDLClose = 1

5 GBase 8a ODBC 连接池

5.1 GBase 8a ODBC 连接池简介

GBase 8a ODBC 连接池是针对 GBase 8a 开发的 ODBC 数据库连接池。它主要有用下几大功能:

  •  缓存连接到 GBase 8a 各节点的数据库连接。
  •  负载功能,根据负载均衡策略将用户申请的连接分摊到 GBase 8a的各节点上。
  •  周期性的维护 GBase 8a ODBC 连接池中各连接的有效性,清理连接池中无效的连接。
  •  周期性的维护连接池中的空闲连接数,保证连接池中的空闲连接数满足用户的设定最大/最小空闲连接数。
  •  清理过期的连接。

5.2 GBase 8a ODBC 连接池使用方法

本节以连接字符串为例来展示 GBase 8a ODBC 连接池的使用方法。主要描述关于连接池的关键字使用方法。在 linux 平台下创建数据源时,同样可以将这些关键字写入到 odbc.ini 文件中来使用 GBase 8a ODBC 连接池功能。或者使用 gsodbc-installer -s -a -c2 -n "test" 加上连接字符串来注册一个带连接池的数据源,如下所示:

#gsodbc-installer -s -a -c2 -n "test" -t “DRIVER=GBase 8a ODBC 8.3 Driver;UID=gbase;PWD=gbase20110531; SERVER=192.168.111.96;”

5.2.1 开启 GBase 8a ODBC 连接池

通过连接字符串开启 GBase 8a ODBC 连接池时,首先要设置 GCLUSTER_ID的值,然后设置 POOL_MAX_ACTIVE_SIZE, POOL_MAX_IDLE 的值大于 0,且POOL_MAX_ACTIVE_SIZE 的值大于等于 POOL_MAX_IDLE 的值。如下所示:

"DRIVER=GBase 8a ODBC 8.3 Driver;UID=gbase;PWD=gbase20110531;"

"SERVER={192.168.111.96;192.168.5.212;192.168.7.174;192.168.7.173};"

"GCLUSTER_ID=gcluster; POOL_MAX_ACTIVE_SIZE=80;POOL_MAX_IDLE=60;" 

5.2.2 设置连接池初始化大小

如果需要在连接初始时让连接池自动创建一定数量的连接,可以通过设置POOL_INIT_SIZE 的值来实现。通常 POOL_INIT_SIZE 的值小于等于POOL_MAX_IDLE。如下所示:

“DRIVER=GBase 8a ODBC 8.3 Driver;UID=gbase;PWD=gbase20110531;”

“SERVER={192.168.111.96;192.168.5.212;192.168.7.174;192.168.7.173};”

“GCLUSTER_ID=gcluster; POOL_MAX_ACTIVE_SIZE=80;POOL_MAX_IDLE=60;”

"POOL_INIT_SIZE=10;" 

5.2.3 设置获取连接超时时间

如果需要限制从连接池获取连接的时间,可以通过设置POOL_CHECKOUT_TIMEOUT 的值来实现。默认情况下 POOL_CHECKOUT_TIMEOUT 值为500 毫秒。如下所示:

“DRIVER=GBase 8a ODBC 8.3 Driver;UID=gbase;PWD=gbase20110531;”

“SERVER={192.168.111.96;192.168.5.212;192.168.7.174;192.168.7.173};”

“GCLUSTER_ID=gcluster; POOL_MAX_ACTIVE_SIZE=80;POOL_MAX_IDLE=60;”

"POOL_CHECKOUT_TIMEOUT=2000;" 

5.2.4 设置获取连接时使用的负载均衡策略

GBase 8a ODBC 连接池提供了两种负载均衡策略,分别是轮询和最小 BUSY连接数优先。使用轮询策略时设置 POOL_LBS=0,使用最小 BUSY 连接数优先策略时设置POOL_LBS=1。默认时使用轮询策略。如下所示:

“DRIVER=GBase 8a ODBC 8.3 Driver;UID=gbase;PWD=gbase20110531;”

“SERVER={192.168.111.96;192.168.5.212;192.168.7.174;192.168.7.173};”

“GCLUSTER_ID=gcluster; POOL_MAX_ACTIVE_SIZE=80;POOL_MAX_IDLE=60;”

"POOL_LBS=1;" 

5.2.5 借还连接时测试连接可用性

从连接池中借出连接时对连接进行测试进一步保证了借出连接的效性,归还连接时对连接进行测试时保证了无效的连接不会进入到连接池中。借出连接时检测需要设置POOL_TEST_BORROW=1,归还连接时检测需要设置POOL_TEST_RETURN=1。如下所示:

“DRIVER=GBase 8a ODBC 8.3 Driver;UID=gbase;PWD=gbase20110531;”

“SERVER={192.168.111.96;192.168.5.212;192.168.7.174;192.168.7.173};”

“GCLUSTER_ID=gcluster; POOL_MAX_ACTIVE_SIZE=80;POOL_MAX_IDLE=60;”

“ POOL_TEST_BORROW=1; POOL_TEST_RETURN=1;”

5.2.6 清理无效连接

如果要连接池定期清理连接池中无效的连接,那么就要设置POOL_MANAGER=1。清理无效连接功能不仅定期清理连接池中无效的连接,还定期检测 GBase 8a 各节点的状态。如果 GBase 8a 有节点恢复可用,GBase 8a ODBC连接池将会缓存连接到该节点的 ODBC 连接。同时通过设置POOL_TEST_INVALID_CONN_PERIOD 的值可以设置清理无效连接的周期。该周期默认值为 20 秒。如下所示:

“DRIVER=GBase 8a ODBC 8.3 Driver;UID=gbase;PWD=gbase20110531;”

“SERVER={192.168.111.96;192.168.5.212;192.168.7.174;192.168.7.173};”

“GCLUSTER_ID=gcluster; POOL_MAX_ACTIVE_SIZE=80;POOL_MAX_IDLE=60;”

" POOL_MANAGER=1;POOL_TEST_INVALID_CONN_PERIOD=30;"

5.2.7 维持空闲连接数

如果要使连接池中的空闲连接数维持在一范围内,那么可以通过设置POOL_KEEP_IDLE=1 打开连接池的空闲连接数维持功能,并设置 POOL_MIN_IDLE的值来实现。POOL_MIN_IDLE 的值小于 POOL_MAX_IDLE 的值。这样当连接池发现空闲连接数小于 POOL_MIN_IDLE 的值时就会创建新的空闲连接,以满足当前空闲连接数大于等于POOL_MIN_IDLE 的值。打开维持空闲连接数功能必须同时设置 POOL_MANAGER=1。如下所示:

“DRIVER=GBase 8a ODBC 8.3 Driver;UID=gbase;PWD=gbase20110531;”

“SERVER={192.168.111.96;192.168.5.212;192.168.7.174;192.168.7.173};”

“GCLUSTER_ID=gcluster; POOL_MAX_ACTIVE_SIZE=80;POOL_MAX_IDLE=60;”

“ POOL_MANAGER=1;POOL_TEST_INVALID_CONN_PERIOD=30;”

" POOL_KEEP_IDLE=1; POOL_MIN_IDLE=30;" 

5.2.8 清理过期连接

用户可以给 GBase 8a ODBC 连接池中的连接设置有效期,并且当连接池发现有连接过期时,会将该连接释放掉。这种功能可以通过设置POOL_CLEAR_OVERDUE,POOL_USED_LIFE 和 POOL_IDLE_LIFE 来打开。如果POOL_USED_LIFE 的值为 0,那么已借出的连接不会过期,POOL_USED_LIFE 默认值为 0;如果 POOL_IDLE_LIFE 的值为 0,那么空闲连接不会过期,POOL_IDLE_LIFE默认值为 0。打开清理过期连接功能必须同时设置 POOL_MANAGER=1 如下所示:

“DRIVER=GBase 8a ODBC 8.3 Driver;UID=gbase;PWD=gbase20110531;”

“SERVER={192.168.111.96;192.168.5.212;192.168.7.174;192.168.7.173};”

“GCLUSTER_ID=gcluster; POOL_MAX_ACTIVE_SIZE=80;POOL_MAX_IDLE=60;”

“ POOL_MANAGER=1;POOL_TEST_INVALID_CONN_PERIOD=30;”

" POOL_CLEAR_OVERDUE=1; POOL_USED_LIFE=360000;

POOL_IDLE_LIFE=36000;" 

5.2.9 释放连接池

释放连接池需要按照如下方式调研释放连接池的接口。

rc = SQLDriverConnect(hdbc, NULL, connStr, SQL_NTS,NULL, 0, NULL,
0);
if (!isSuc(rc))
{
getError(SQL_HANDLE_DBC, hdbc);
return;
}
SQLSetConnectAttr(hdbc, SQL_ATTR_GBASE_POOL_FREE,
SQL_FREE_GBASE_POOL, NULL);
SQLDisconnect(hdbc);

在归还从连接池借出的连接前,先设置该连接的属性SQL_ATTR_GBASE_POOL_FREE 的值为 SQL_FREE_GBASE_POOL,然后调用SQLDisconnect 归还连接。这样 ODBC 在归还连接的同时会释放掉该连接所在的连接池。

5 GBase 8a ODBC 应用示例

5.1高可用性示例

#ifdef WIN32
#include<windows.h>
#else
#include<unistd.h>
#endif
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sql.h>
#include<sqlext.h>
#define isSuc(result) ((result) == SQL_SUCCESS || (result) ==SQL_SUCCESS_WITH_INFO)
char hosts[][100] = {"192.168.5.64",
"192.168.5.65",
"192.168.5.64;192.168.5.65",
"192.168.5.65;192.168.5.64",
"192.168.5.64;192.168.5.64",
"192.168.5.64;192.168.5.64;192.168.5.65",
"192.168.5.64;192.168.5.65;192.168.5.64",
"192.168.5.65;192.168.5.64;192.168.5.64",
"192.168.5.65;192.168.5.66",
NULL};
int main(void)
{
char conn_format[200] = "DRIVER={GBase 8a ODBC 8.3 Driver};"
"SERVER={%s};UID=root;PWD=1;DATABASE=test;PORT=5258;";
char conn[200] = {'\0'};
int i = 0;
short sret; //返回代码
void* henv; //环境句柄
void* hdbc; //连接句柄
/** 申请环境句柄**/
sret =SQLAllocHandle(SQL_HANDLE_ENV,SQL_NULL_HANDLE,&henv);
if(!isSuc(sret))printf("申请环境句柄出错\n");
/** 设置环境属性,声明 ODBC 版本**/
sret =SQLSetEnvAttr(henv,SQL_ATTR_ODBC_VERSION,(void*)SQL_OV_ODBC3,0);
if(!isSuc(sret))printf("声明 ODBC 版本出错\n");
/** 申请连接句柄**/
sret = SQLAllocHandle(SQL_HANDLE_DBC,henv,&hdbc);
if(!isSuc(sret))printf("申请连接句柄出错\n");
/** 设置连接属性**/
sret = SQLSetConnectAttr(hdbc,SQL_ATTR_AUTOCOMMIT,
GBase 8a 程序员手册 ODBC 篇
南大通用数据技术股份有限公司 - 61 -
(void*)SQL_AUTOCOMMIT_OFF,SQL_IS_INTEGER);
if(!isSuc(sret))printf("设置连接属性出错\n");
while(*hosts[i])
{
sprintf(conn, conn_format, hosts[i]);
/** 连接数据源**/
sret = SQLDriverConnect(hdbc,NULL,(unsigned char *)conn,
SQL_NTS, NULL, 0, NULL, 0);
if(!isSuc(sret))printf("连接%s 出错\n", hosts[i]);
else printf("连接%s 成功\n", hosts[i]);
SQLDisconnect(hdbc);
memset(conn, '\0', strlen(conn));
i++;
}
return 0;
}

5.2 负载均衡示例

#ifdef WIN32
# include <windows.h>
#else
# include <unistd.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <sql.h>
#include <sqlext.h>
#define isSuc(result) ((result) == SQL_SUCCESS || (result) ==SQL_SUCCESS_WITH_INFO)
char* conn_str = "DRIVER=GBase 8a ODBC 8.3
Driver;UID=gbase;PWD=gbase20110531;"
"SERVER={192.168.7.172;192.168.7.173;192.168.7.174};"
"CONNECTION_BALANCE=1;GCLUSTER_ID=gcluster;"
"CHECK_INTERVAL=90;";
int main(void)
{
short sret;
void* henv;
void* hdbc;
char message[512];
char hostinfo[100];
int i = 0;
sret = SQLAllocHandle(SQL_HANDLE_ENV,SQL_NULL_HANDLE,&henv);
if(!isSuc(sret))
{
SQLGetDiagRec(SQL_HANDLE_ENV, henv, 1, NULL, NULL,
(SQLCHAR*)message, 1023, NULL);
printf("%s\n", message);
return -1;
}
sret =
SQLSetEnvAttr(henv,SQL_ATTR_ODBC_VERSION,(void*)SQL_OV_ODBC3,0);
if(!isSuc(sret))
{
SQLGetDiagRec(SQL_HANDLE_ENV, henv, 1, NULL, NULL,
(SQLCHAR*)message, 1023, NULL);
printf("%s\n", message);
return -1;
}
sret = SQLAllocHandle(SQL_HANDLE_DBC,henv,&hdbc);
if(!isSuc(sret))
{
SQLGetDiagRec(SQL_HANDLE_ENV, henv, 1, NULL, NULL,
(SQLCHAR*)message, 1023, NULL);
printf("%s\n", message);
return -1;
}
for (i=0; i<6; i++)
{
sret = SQLDriverConnect(hdbc, NULL,(SQLCHAR*)conn_str,
SQL_NTS,NULL, 0, NULL, 0);
if(!isSuc(sret))
{
SQLGetDiagRec(SQL_HANDLE_DBC, hdbc, 1, NULL, NULL,
(SQLCHAR*)message, 1023, NULL);
printf("%s\n", message);
return -1;
}
SQLGetInfo(hdbc, SQL_SERVER_NAME, hostinfo, 200, NULL);
printf("使用 GBase 8a ODBC 高可用负载均衡连接 GBase 集群节
点:%s.\n", hostinfo);
sret = SQLDisconnect(hdbc);
if(!isSuc(sret))
{
SQLGetDiagRec(SQL_HANDLE_DBC, hdbc, 1, NULL, NULL,
(SQLCHAR*)message, 1023, NULL);
printf("%s\n", message);
return -1;
}
}
sret = SQLFreeConnect(hdbc);
if(!isSuc(sret))
{
SQLGetDiagRec(SQL_HANDLE_DBC, hdbc, 1, NULL, NULL,
(SQLCHAR*)message, 1023, NULL);
printf("%s\n", message);
return -1;
}
sret = SQLFreeEnv(henv);
if(!isSuc(sret))
{
SQLGetDiagRec(SQL_HANDLE_ENV, henv, 1, NULL, NULL,
(SQLCHAR*)message, 1023, NULL);
printf("%s\n", message);
return -1;
}
return 0;
}

5.3 连接池示例

#ifdef WIN32
# include <windows.h>
# define sleep(x) Sleep(x*1000)
#else
# include <unistd.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <sql.h>
#include <sqlext.h>
#include <time.h>
#include "sqlgbase.h"
#define isSuc(result) ((result) == SQL_SUCCESS || (result) ==
SQL_SUCCESS_WITH_INFO)
#define FOR_TIMES 50
#define CON_NUM 50
SQLHANDLE henv;
int seg;
#ifdef WIN32
CRITICAL_SECTION thread_quit_lock;
#define THREAD_ID() GetCurrentThreadId()
#else
pthread_mutex_t thread_quit_lock;
#define THREAD_ID() pthread_self()
#endif
void getError(SQLSMALLINT type, SQLHANDLE handle)
{
SQLCHAR sqlstate[1024];
SQLCHAR errormes[1024];
SQLINTEGER numerror;
SQLSMALLINT errlen;
SQLGetDiagRec(type, handle, 1, sqlstate, &numerror, errormes,
1024, &errlen);
printf("sqlstate:%s\terrmsg:%s\terrno:%d\n",sqlstate,
errormes, numerror);
}
char* connStr = "DRIVER=GBase 8a ODBC 8.3
Driver;UID=gbase;PWD=gbase20110531;"
"SERVER={192.168.9.173;192.168.9.174;192.168.9.175};DATABASE
=test; PORT=5258;"
"GCLUSTER_ID=aaa;POOL_MAX_ACTIVE_SIZE=70;POOL_MAX_IDLE=65;"
"POOL_INIT_SIZE=10;"
"POOL_TEST_BORROW=0;"
"POOL_LBS=1;"
“POOL_CHECKOUT_TIMEOUT=5000;”
"POOL_MANAGER=1;"
"POOL_TEST_INVALID_CONN_PERIOD=2000;"
"POOL_KEEP_IDLE=1; POOL_MIN_IDLE=12;"
"POOL_CLEAR_OVERDUE=1; POOL_USED_LIFE=400000;
POOL_IDLE_LIFE=0;";
#ifdef WIN32
DWORD WINAPI thread_bf(LPVOID arg)
#else
int thread_bf(void* arg)
#endif
{
SQLHDBC hdbc;
SQLHANDLE hsmt;
int sret = 0;
int i =0 ;
clock_t t1, t2;
time_t t;
int rc = 0;
while(i < FOR_TIMES)
{
t1 = t2 = clock();
SQLAllocHandle(SQL_HANDLE_DBC,henv,&hdbc);
sret = SQLDriverConnect(hdbc, NULL, connStr, SQL_NTS,NULL,
0, NULL, 0);
if (!isSuc(sret))
{
getError(SQL_HANDLE_DBC, hdbc);
}
else
{
t2 = clock();
time(&t);
printf("thread id %u\t\tconnect success! use %lu
msec\t%s.\n",THREAD_ID(), (t2 - t1), ctime(&t));
rc = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hsmt);
if (rc == SQL_SUCCESS)
{
SQLExecDirect(hsmt, "show databases", strlen("show
databases"));
SQLFreeHandle(SQL_HANDLE_STMT, hsmt);
}
SQLDisconnect(hdbc);
SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
}
i++;
}
#ifdef WIN32
EnterCriticalSection(&thread_quit_lock);
seg--;
LeaveCriticalSection(&thread_quit_lock);
#else
pthread_mutex_lock(&thread_quit_lock);
seg--;
pthread_mutex_unlock(&thread_quit_lock);
#endif
return 0;
}
void t1_bf()
{
SQLHDBC hdbc;
int rc = 0, i = 0;
#ifdef WIN32
InitializeCriticalSection(&thread_quit_lock);
#else
pthread_mutex_init(&thread_quit_lock, NULL);
#endif
SQLAllocHandle(SQL_HANDLE_ENV,SQL_NULL_HANDLE,&henv);
SQLSetEnvAttr(henv,SQL_ATTR_ODBC_VERSION,(void*)SQL_OV_O
DBC3,0);
seg = CON_NUM;
while(i<CON_NUM)
{
#ifdef WIN32
CreateThread(NULL, 0, thread_bf, NULL, 0, NULL);
#else
pthread_t thread;
pthread_create(&thread, 0, thread_bf, NULL);
#endif
i++;
}
while(seg > 0)sleep(1);
SQLAllocHandle(SQL_HANDLE_DBC,henv,&hdbc);
rc = SQLDriverConnect(hdbc, NULL, connStr, SQL_NTS,NULL, 0, NULL,
0);
if (!isSuc(rc))
{
getError(SQL_HANDLE_DBC, hdbc);
return;
}
SQLSetConnectAttr(hdbc, SQL_ATTR_GBASE_POOL_FREE,
SQL_FREE_GBASE_POOL, NULL);
SQLDisconnect(hdbc);
SQLFreeHandle(SQL_HANDLE_ENV, henv);
}

今天的内容就给大家介绍这些,希望对大家有所帮助,感谢~

原文链接:https://www.gbase.cn/community/post/4307
更多精彩内容尽在南大通用GBase技术社区,南大通用致力于成为用户最信赖的数据库产品供应商。

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值