开启连接池
前提条件:数据源已配置成功。Linux系统请参考Linux下配置数据源;Windows系统请参考Windows下配置数据源。
在Linux和Windows环境下开启连接池,对于需要频繁建立和断开连接的中间层应用程序可显著提升性能,参考配置请参见连接池场景,示例代码如下:
#ifdef WIN32
#include <windows.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <sql.h>
#include <sqlext.h>
#include <string.h>
#include <sys/time.h>
#include <pthread.h>
#include <sqltypes.h>
#include <time.h>
SQLHENV env;
SQLHDBC conn;
struct timeval start, end;
#define CONN_COUNT 15000
#define CHECK_ERROR(retcode, str, handle, htype) \
({ \
if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO) { \
fprintf(stderr, "FAILED:\t"); \
extract_error(str, handle, htype); \
exit(-1); \
} else { \
printf("OK:\t%s\n", str); \
} \
})
void print_diag(char *msg, SQLSMALLINT htype, SQLHANDLE handle)
{
char sqlstate[32];
char message[1000];
SQLINTEGER nativeerror;
SQLSMALLINT textlen;
SQLRETURN ret;
if (msg) {
printf("%s\n", msg);
}
ret = SQLGetDiagRec(htype, handle, 1, sqlstate, &nativeerror, message, 256, &textlen);
if (ret != SQL_ERROR) {
printf("%s=%s\n", (CHAR *)sqlstate, (CHAR *)message);
}
}
void extract_error(char *fn, SQLHANDLE handle, SQLSMALLINT type)
{
SQLINTEGER i = 0;
SQLINTEGER NativeError;
SQLCHAR SQLState[7];
SQLCHAR MessageText[256];
SQLSMALLINT TextLength;
SQLRETURN ret;
fprintf(stderr, "The driver reported the following error %s\n", fn);
if (NULL == handle)
return;
do {
ret = SQLGetDiagRec(type, handle, ++i, SQLState, &NativeError, MessageText, sizeof(MessageText), &TextLength);
if (SQL_SUCCEEDED(ret)) {
printf("[SQLState:%s]:[%ldth error]:[NativeError:%ld]: %s\n",
SQLState,
(long)i,
(long)NativeError,
MessageText);
}
} while (ret == SQL_SUCCESS);
}
void InitializeEnvironment()
{
/* Windows配置连接池参数,需要在分配环境句柄前完成,此处为开启连接池 */
SQLSetEnvAttr(env, SQL_ATTR_CONNECTION_POOLING, (SQLINTEGER *)SQL_CP_ONE_PER_DRIVER, 0);
/* 在Win上关闭连接池 */
// SQLSetEnvAttr(env, SQL_ATTR_CONNECTION_POOLING, (SQLINTEGER*)SQL_CP_OFF, 0);
// 分配环境句柄
SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env);
// 配置ODBC版本
SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, 0);
// 配置建连超时时间
SQLSetConnectAttr(conn, SQL_LOGIN_TIMEOUT, (SQLPOINTER *)5, 0);
}
void test_connect()
{
SQLRETURN ret;
SQLCHAR str[1024];
SQLSMALLINT strl;
SQLCHAR dsn[1024];
SQLUINTEGER uIntVal;
SQLAllocHandle(SQL_HANDLE_DBC, env, &conn);
/* 根据场景需要调整连接串 */
char *config = "Driver=GaussMPP;DSN=gaussdb;";
ret = SQLSetConnectAttr(conn, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)(1), 0);
ret = SQLDriverConnect(conn, 0, (SQLCHAR *)config, SQL_NTS, (SQLCHAR *)NULL, SQL_NTS, 0, SQL_DRIVER_NOPROMPT);
if (SQL_SUCCEEDED(ret)) {
// printf("Connected\n");
} else {
print_diag("SQLDriverConnect failed.", SQL_HANDLE_DBC, conn);
SQLFreeHandle(SQL_HANDLE_DBC, conn);
SQLFreeHandle(SQL_HANDLE_ENV, env);
exit(1);
}
/* 将连接放入连接池以重用连接 */
if (conn != SQL_NULL_HDBC) {
SQLDisconnect(conn);
SQLFreeHandle(SQL_HANDLE_DBC, conn);
conn = SQL_NULL_HDBC;
}
}
int main()
{
int count = 0;
int timeuser;
gettimeofday(&start, NULL);
InitializeEnvironment();
for (int i = 0; i < CONN_COUNT; i++) {
test_connect();
count++;
}
//释放环境句柄
SQLFreeHandle(SQL_HANDLE_ENV, env);
printf("Connection count: %d\n", count);
gettimeofday(&end, NULL);
timeuser = 1000000 * (end.tv_sec - start.tv_sec) + end.tv_usec - start.tv_usec;
printf("Connection time: %.3f s \n", (double)timeuser / 1000000);
return 0;
}
不同环境下结果不一,在连接池打开的情况下,本示例运行结果如下:
Connection count: 15000 Connection time: 14.175 s
在连接池关闭的情况下,本示例运行结果如下:
Connection count: 15000 Connection time: 691.768 s
Windows环境应用代码同Linux环境如上,连接串需根据场景进行配置。