您的位置:首页 > 数据库 > MySQL

简单mysql连接池

2016-03-13 15:47 501 查看
原文链接:http://blog.sina.com.cn/s/blog_49f761940100nv39.html

原文链接:
http://blog.csdn.net/midle110/article/details/19564463
版本一:

连接池为了解决频繁的创建、销毁所带来的系统开销。

简而言之,就是 自己先创建一定量的连接,然后在需要的时候取出一条连接使用。

当然如果你只有一个线程连接数据库,而且不是实时返回结果,那么你完全不必用连接池。

想一下网络大型游戏服务器,你就明白为什么需要连接池了。

自己敲代码写了一个简单的类,实现连接池,虽然没有mysql++那么强大,但是还是自己有收获。

Csqlpool.h 头文件实现如下:

[cpp] view
plain copy







#pragma once

#include <WinSock2.h>

#include <mysql.h>

#include <list>

#pragma comment( lib , "libmysql.lib" )

using namespace std;

class Csqlpool

{

public:

~Csqlpool(void);

static Csqlpool *GetSqlPool();

bool IniSqlPool( const char *host , const char *name , const char *pwd , unsigned int port , unsigned int conMax ); //初始化连接池

bool SelectDB( MYSQL *sql, const char *DB); //选择数据库

MYSQL *GetConnect(); // 获取连接

void RelConnect(MYSQL *sql) ; // 释放连接

MYSQL_RES* GetQuery( MYSQL *sql , const char *query); //mysql操作 增删查改

void RelQuery(MYSQL_RES *res); //释放MYSQL_RES资源

bool Query(MYSQL *sql , const char *query); //增、删、改操作

protected:

Csqlpool(void);

private:

list<MYSQL *> m_sql_free; //空闲连接

static Csqlpool *pSqlPool;

CRITICAL_SECTION m_session; //获取空闲线程

};

Csqlpool.cpp 实现如下:

[cpp] view
plain copy







#include "StdAfx.h"

#include "Csqlpool.h"

Csqlpool *Csqlpool::pSqlPool = NULL;

Csqlpool::Csqlpool(void)

{

InitializeCriticalSection( &m_session );

}

Csqlpool::~Csqlpool(void)

{

while ( m_sql_free.size() )

{

mysql_close( m_sql_free.front() );

m_sql_free.pop_front();

}

DeleteCriticalSection(&m_session);

}

Csqlpool* Csqlpool::GetSqlPool()

{

if ( pSqlPool == NULL )

{

return new Csqlpool;

}

return pSqlPool;

}

bool Csqlpool::IniSqlPool( const char *host ,const char *name , const char *pwd , unsigned int port , unsigned int conMax ) //初始化连接池

{

int nsum = 0 ;

for (unsigned int i = 0 ; i < conMax ;++i )

{

MYSQL *pmysql;

pmysql = mysql_init( (MYSQL*)NULL );

if ( pmysql != NULL )

{

if ( mysql_real_connect( pmysql , host , name , pwd , NULL , 3306 , NULL , 0 ) )

{

m_sql_free.push_back(pmysql);

}

else

{

if ( nsum++ == 100 )

{

return false;

}

continue;

}

}

continue;

}

return true;

}

bool Csqlpool::SelectDB( MYSQL *sql, const char *DB) //选择数据库

{

if(mysql_select_db(sql , DB))

{

return false;

}

return true;

}

MYSQL* Csqlpool::GetConnect() // 获取连接

{

if ( m_sql_free.size() )

{

EnterCriticalSection(&m_session);

MYSQL *mysql = m_sql_free.front();

m_sql_free.pop_front();

LeaveCriticalSection(&m_session);

return mysql;

}

else

return NULL;

}

void Csqlpool::RelConnect(MYSQL *sql) // 释放连接

{

EnterCriticalSection(&m_session);

m_sql_free.push_back(sql);

LeaveCriticalSection(&m_session);

}

MYSQL_RES* Csqlpool::GetQuery( MYSQL *sql , const char *query) //查询操作

{

if ( mysql_query( sql , query ) == 0 )

{

return mysql_store_result( sql );

}

else

return NULL;

}

void Csqlpool::RelQuery(MYSQL_RES *res) //mysql_res release

{

mysql_free_result(res);

}

bool Csqlpool::Query(MYSQL *sql , const char *query) //增、删、改操作

{

if ( mysql_query( sql , query ) )

{

return false;

}

return true;

}

testsqlpool.cpp 测试文件实现如下:

[cpp] view
plain copy







// testsqlpool.cpp : 定义控制台应用程序的入口点。

//

#include "stdafx.h"

#include "Csqlpool.h"

#include <iostream>

using namespace std;

Csqlpool *psql = Csqlpool::GetSqlPool();

DWORD WINAPI ThreadProc( LPVOID lpParameter);

int _tmain(int argc, _TCHAR* argv[])

{

if(!psql->IniSqlPool("127.0.0.1" , "root" ,"123",3306,10))

{

cout<<"连接错误"<<endl;

}

HANDLE phan[2] ;

DWORD threadid[2];

int n1 = 0, n2 = 100;;

phan[0] = CreateThread( NULL , 0 , ThreadProc , &n1 , 0 , &threadid[0] );

phan[1] = CreateThread( NULL , 0 , ThreadProc , &n2 , 0 , &threadid[1] );

WaitForMultipleObjects( 2 , phan , true , INFINITE );

CloseHandle(phan[0]);

CloseHandle(phan[1]);

return 0;

}

DWORD WINAPI ThreadProc( LPVOID lpParameter)

{

int index = *(int *)lpParameter ;

int i = 1;

MYSQL *sql = psql->GetConnect();

string stemp = "insert into actor( actor_id , first_name , last_name,last_update )values(\"";

string strsql;

char str[10];

if ( psql->SelectDB(sql , "sakila") )

{

while ( i != 100 )

{

sprintf( str , "%d" , i+index );

strsql = stemp ;

strsql += str;

strsql += "\",\"0\",\"0\",\"0\")";

if(!sql)

return 0;

if(!psql->Query( sql ,strsql.c_str() ))

{

cout<<"add false"<<endl;

}

++i;

}

psql->RelConnect(sql);

}

return 0;

}

版本二:

一、头文件【存为:connPool.h】

#ifndef __CONNECTION_POOL_H__

#define __CONNECTION_POOL_H__

#include "mutex.h"

#define MYSQL_CONN_NUM_MAX_VALUE 500

using namespace std;

enum _USE_STATUS

{

US_USE = 0,

US_IDLE = 1

};

typedef struct _sConStatus

{

void* connAddr;

int useStatus;

}sConStatus;

class CConnPool

{

public:

CConnPool();

~CConnPool();

public:

int Init(string& strMysqlIp, string& strUser, string& strPwd, string& strDbName, int nMysqlPort, int nConnNum);//connection pool init

void* getOneConn();//get a connection

void retOneConn(void* pMysql);// return a connection

void checkConn(); // check the connection if is alive

void* createOneConn();

public:

char m_szMysqlIp[100];

char m_szUser[100];

char m_szPwd[100];

char m_szDbName[100];

int m_nMysqlPort;

int m_nConnNum;

public:

CMutex m_sMutex;

vector<void*> m_vectorConn;

map<void*, int> m_mapVI;

map<void*, void*> m_mapMysqlScs;

};

class CConnPoolV2

{

public:

CConnPoolV2();

~CConnPoolV2();

public:

int Init(string& strMysqlIp, string& strUser, string& strPwd, string& strDbName, int nMysqlPort, int nConnNum);//connection pool init

void* getOneConn(); //从连接池取一个连接

void retOneConn(void* pConn);// 连接用完了,把它放回连接池。以便其他人用。

void checkConn(); // check the connection if is alive

void* createOneConn();

private:

string m_strMysqlIp;

string m_strUser;

string m_strPwd;

string m_strDbName;

int m_nMysqlPort;

int m_nConnNum;

private:

CMutex m_sMutex;

vector<void*> m_vectorConn;

map<void*, int> m_mapVI; // 从连接的地址,快速找到索引,便于存放到m_vectorConn中。

};

#endif

二、源码【存为:connPool.cpp】

#include <stdio.h>

#include <stdlib.h>

#include <errno.h>

#include <string.h>

#include <sys/types.h>

#include <netinet/in.h>

#include <sys/socket.h>

#include <sys/wait.h>

#include <arpa/inet.h>

#include <unistd.h>

#include <fcntl.h>

#include <pthread.h>

#include <time.h>

#include <iostream>

#include <memory>

#include <string>

#include <map>

#include <vector>

#include "mysql.h"

#include "encapsulation_mysql.h"

#include "connPool.h"

#include "mutex.h"

using namespace std;

using namespace EncapMysql;

CConnPool::CConnPool( )

{

}

CConnPool::~CConnPool( )

{

}

void* CConnPool::createOneConn()

{

MYSQL* mysql;

mysql = mysql_init(0);

if(mysql == NULL)

{

cout << "mysql_init fail**" << endl;

return NULL;

}

if(mysql_real_connect(mysql, m_szMysqlIp , m_szUser , m_szPwd, m_szDbName , m_nMysqlPort, NULL,0)==NULL)

{

cout << "connect failure!" << endl;

return NULL;

}

else

{

cout << "connect success!" << endl;

}

//

return mysql;

}

int CConnPool::Init(string& strMysqlIp, string& strUser, string& strPwd, string& strDbName, int nMysqlPort, int nConnNum)

{

strcpy(m_szMysqlIp, strMysqlIp.c_str());

strcpy( m_szUser, strUser.c_str());

strcpy(m_szPwd, strPwd.c_str());

strcpy(m_szDbName, strDbName.c_str());

m_nMysqlPort = nMysqlPort;

m_nConnNum = nConnNum;

MYSQL* mysql;

for(int i=0; i<nConnNum; i++)

{

mysql = (MYSQL*)this->createOneConn();

if(mysql == NULL)

return -1;

//

sConStatus* scs = new sConStatus();

scs->connAddr = mysql;

scs->useStatus = US_IDLE;

m_vectorConn.push_back(scs);

m_mapVI[scs] = i;

m_mapMysqlScs[mysql] = scs;

}

m_nConnNum = nConnNum;

}

//从连接池中取一个连接,同时,给它做一个标记,表明它已经被使用,防止别的线程再使用。

void* CConnPool::getOneConn()

{

int N = m_vectorConn.size();

for(int i=0; i< N; i++)

{

CGuard guard(m_sMutex);

sConStatus* scs = (sConStatus*)m_vectorConn[i];

if(scs->useStatus == US_IDLE)

{

scs->useStatus = US_USE;

return scs->connAddr;

}

}

//

return NULL;

}

//把连接归还给连接池。同时,给它做一个标记,表明它是空闲的,可以使用。

void CConnPool::retOneConn(void* pMysql)

{

if(!pMysql)

return;

//

map<void*, void*>::iterator it1;

map<void*, int>::iterator it2;

CGuard guard(m_sMutex);

it1 = m_mapMysqlScs.find(pMysql);

if(it1 == m_mapMysqlScs.end())

return;

it2 = m_mapVI.find(it1->second);

if(it2 == m_mapVI.end())

return;

int nInx = it2->second;

sConStatus* scs = (sConStatus*) m_vectorConn[nInx];

scs->useStatus = US_IDLE;

}

void CConnPool::checkConn()

{

map<void*, void*>::iterator it1;

MYSQL* mysql;

//

for(int i=0; i<m_nConnNum ; i++)

{

CGuard guard(m_sMutex);

sConStatus* scs = (sConStatus*)m_vectorConn[i];

if(scs->useStatus == US_USE)

continue;

//

mysql =(MYSQL*)(scs->connAddr);

int status=mysql_query(mysql, "select count(*) from t_user;" );

if(status != 0) //说明连接已经不可用了。

{

it1 = m_mapMysqlScs.find(mysql);

if(it1 != m_mapMysqlScs.end())

{

m_mapMysqlScs.erase(it1);

}

//

mysql_close(mysql);

//

mysql = (MYSQL*)this->createOneConn();

m_mapMysqlScs[mysql] = scs;

}

}

//

}

////////////////////////////// 2011-01-20, 这个类这样写,感觉耦合性更为松散,比较好。使用起来也好理解一些。

CConnPoolV2::CConnPoolV2( )

{

}

CConnPoolV2::~CConnPoolV2( )

{

}

//创建一个连接,并设为 IDLE状态。

void* CConnPoolV2::createOneConn()

{

try

{

CEncapMysql* pEM = new CEncapMysql();

if(pEM == NULL)

{

printf("pEM == NULL**\r\n");

return NULL;

}

//

int nRet = pEM->Connect(m_strMysqlIp.c_str(), m_strUser.c_str(), m_strPwd.c_str());

if(nRet != 0)

{

printf("pEM->Connect fail**\r\n");

return NULL;

}

//

pEM->SetIdle();

//

return pEM;

}

catch(...)

{

printf("createOneConn exception**\r\n");

return NULL;

}

}

//成功: 返回0

int CConnPoolV2::Init(string& strMysqlIp, string& strUser, string& strPwd, string& strDbName, int nMysqlPort, int nConnNum)

{

m_strMysqlIp = strMysqlIp;

m_strUser = strUser;

m_strPwd = strPwd;

m_strDbName = strDbName;

m_nMysqlPort = nMysqlPort;

m_nConnNum = nConnNum;

CEncapMysql* pEM;

int nRet;

for(int i=0; i<nConnNum; i++)

{

pEM = (CEncapMysql*)this->createOneConn();

if(!pEM )

return -1;

//

m_vectorConn.push_back(pEM);

m_mapVI[pEM] = i;

}

return 0;

}

void* CConnPoolV2::getOneConn()

{

CGuard guard(m_sMutex);

//

for(int i=0; i< m_nConnNum; i++)

{

CEncapMysql* pEM = (CEncapMysql*)m_vectorConn[i];

if( pEM->IsIdle())

{

pEM->SetUsed();

return pEM;

}

}

//可能访问MYSQL的用户较多,连接池中已无空闲连接了。 只要总连接数没有超限,就新建一个连接。

if(m_nConnNum < MYSQL_CONN_NUM_MAX_VALUE)

{

CEncapMysql* pEM = (CEncapMysql*)this->createOneConn();

if(!pEM )

return NULL;

//

m_vectorConn.push_back(pEM);

m_mapVI[pEM] = m_nConnNum++;

}

//

return NULL;

}

void CConnPoolV2::retOneConn(void* pConn)

{

map<void*, int>::iterator it;

CGuard guard(m_sMutex);

it = m_mapVI.find(pConn);

if(it == m_mapVI.end())

{

printf("retOneConn fail***\n");

return;

}

int nInx = it->second;

CEncapMysql* pEM = (CEncapMysql*) m_vectorConn[nInx];

pEM->SetIdle();

printf("retOneConn succ!\n");

}

void CConnPoolV2::checkConn()

{

//暂时可以不实现。 因为查询失败时,已重新连接了。

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: