简单mysql连接池

来源:互联网 发布:sql server sum 函数 编辑:程序博客网 时间:2024/06/15 05:14

原文链接:http://blog.sina.com.cn/s/blog_49f761940100nv39.html

原文链接:

http://blog.csdn.net/midle110/article/details/19564463


版本一:

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

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

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

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

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


Csqlpool.h 头文件实现如下:

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. #pragma once  
  2. #include <WinSock2.h>  
  3. #include <mysql.h>  
  4. #include <list>  
  5.   
  6. #pragma comment( lib , "libmysql.lib" )  
  7.   
  8. using namespace std;  
  9.   
  10. class Csqlpool  
  11. {  
  12. public:  
  13.     ~Csqlpool(void);  
  14.     static Csqlpool *GetSqlPool();  
  15.     bool IniSqlPool( const char *host , const char *name , const char *pwd , unsigned int port , unsigned int conMax );  //初始化连接池  
  16.     bool SelectDB( MYSQL *sql, const char *DB); //选择数据库  
  17.     MYSQL *GetConnect();          // 获取连接  
  18.     void RelConnect(MYSQL *sql) ;  // 释放连接  
  19.     MYSQL_RES* GetQuery( MYSQL *sql , const char *query);      //mysql操作  增删查改  
  20.     void RelQuery(MYSQL_RES *res);   //释放MYSQL_RES资源  
  21.   
  22.     bool Query(MYSQL *sql , const char *query);  //增、删、改操作  
  23.   
  24.   
  25. protected:  
  26.     Csqlpool(void);  
  27. private:  
  28.     list<MYSQL *> m_sql_free;   //空闲连接       
  29.     static Csqlpool *pSqlPool;        
  30.     CRITICAL_SECTION m_session;    //获取空闲线程  
  31. };  


Csqlpool.cpp 实现如下:

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. #include "StdAfx.h"  
  2. #include "Csqlpool.h"  
  3.   
  4. Csqlpool *Csqlpool::pSqlPool = NULL;  
  5.   
  6.   
  7. Csqlpool::Csqlpool(void)  
  8. {  
  9.     InitializeCriticalSection( &m_session );  
  10. }  
  11.   
  12.   
  13. Csqlpool::~Csqlpool(void)  
  14. {  
  15.     while ( m_sql_free.size() )  
  16.     {  
  17.         mysql_close( m_sql_free.front() );  
  18.         m_sql_free.pop_front();  
  19.     }  
  20.     DeleteCriticalSection(&m_session);  
  21. }  
  22.   
  23.   
  24. Csqlpool* Csqlpool::GetSqlPool()  
  25. {  
  26.     if (  pSqlPool == NULL )  
  27.     {  
  28.         return new Csqlpool;  
  29.     }  
  30.     return pSqlPool;  
  31. }  
  32.   
  33. bool Csqlpool::IniSqlPool( const char *host ,const char *name , const char *pwd , unsigned int port , unsigned int conMax )  //初始化连接池  
  34. {  
  35.     int nsum = 0 ;  
  36.     for (unsigned int i = 0 ; i < conMax ;++i  )  
  37.     {  
  38.         MYSQL *pmysql;  
  39.         pmysql = mysql_init( (MYSQL*)NULL );  
  40.         if ( pmysql != NULL )  
  41.         {  
  42.             if ( mysql_real_connect( pmysql , host , name , pwd , NULL , 3306 , NULL , 0 ) )  
  43.             {  
  44.                 m_sql_free.push_back(pmysql);  
  45.             }  
  46.             else  
  47.             {  
  48.                 if ( nsum++ == 100 )  
  49.                 {  
  50.                     return false;  
  51.                 }  
  52.                 continue;  
  53.             }  
  54.         }  
  55.         continue;  
  56.     }  
  57.     return true;  
  58. }  
  59.   
  60. bool Csqlpool::SelectDB( MYSQL *sql, const char *DB)    //选择数据库  
  61. {  
  62.     if(mysql_select_db(sql , DB))  
  63.     {  
  64.         return false;  
  65.     }  
  66.     return true;  
  67. }  
  68.   
  69. MYSQL* Csqlpool::GetConnect()          // 获取连接  
  70. {  
  71.     if ( m_sql_free.size()  )  
  72.     {  
  73.         EnterCriticalSection(&m_session);  
  74.         MYSQL *mysql = m_sql_free.front();  
  75.         m_sql_free.pop_front();  
  76.         LeaveCriticalSection(&m_session);  
  77.         return mysql;  
  78.     }  
  79.     else  
  80.         return NULL;  
  81. }  
  82.   
  83. void Csqlpool::RelConnect(MYSQL *sql)  // 释放连接  
  84. {  
  85.     EnterCriticalSection(&m_session);  
  86.     m_sql_free.push_back(sql);  
  87.     LeaveCriticalSection(&m_session);  
  88. }  
  89.   
  90.   
  91. MYSQL_RES* Csqlpool::GetQuery( MYSQL *sql , const char *query)         //查询操作  
  92. {  
  93.     if ( mysql_query( sql , query ) == 0 )  
  94.     {  
  95.         return mysql_store_result( sql );  
  96.     }  
  97.     else  
  98.         return NULL;  
  99. }  
  100.   
  101. void Csqlpool::RelQuery(MYSQL_RES *res)   //mysql_res release  
  102. {  
  103.     mysql_free_result(res);  
  104. }  
  105.   
  106. bool Csqlpool::Query(MYSQL *sql , const char *query)  //增、删、改操作  
  107. {  
  108.     if ( mysql_query( sql , query ) )  
  109.     {  
  110.         return false;  
  111.     }  
  112.     return true;  
  113. }  


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

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. // testsqlpool.cpp : 定义控制台应用程序的入口点。  
  2. //  
  3.   
  4. #include "stdafx.h"  
  5. #include "Csqlpool.h"  
  6. #include <iostream>  
  7.   
  8. using namespace std;  
  9.   
  10.   
  11. Csqlpool *psql = Csqlpool::GetSqlPool();  
  12.   
  13. DWORD WINAPI ThreadProc( LPVOID lpParameter);  
  14.   
  15. int _tmain(int argc, _TCHAR* argv[])  
  16. {  
  17.   
  18.     if(!psql->IniSqlPool("127.0.0.1" , "root" ,"123",3306,10))  
  19.     {  
  20.         cout<<"连接错误"<<endl;  
  21.     }  
  22.   
  23.   
  24.     HANDLE phan[2] ;  
  25.     DWORD threadid[2];  
  26.     int n1 = 0, n2 = 100;;  
  27.     phan[0]  = CreateThread( NULL , 0 ,  ThreadProc , &n1 ,  0 , &threadid[0] );  
  28.     phan[1]  = CreateThread( NULL , 0 , ThreadProc , &n2 ,   0 , &threadid[1] );  
  29.     WaitForMultipleObjects( 2 , phan , true ,  INFINITE );  
  30.   
  31.     CloseHandle(phan[0]);  
  32.     CloseHandle(phan[1]);  
  33.   
  34.     return 0;  
  35. }  
  36.   
  37. DWORD WINAPI ThreadProc( LPVOID lpParameter)  
  38. {  
  39.     int index = *(int *)lpParameter ;  
  40.     int i = 1;   
  41.     MYSQL *sql = psql->GetConnect();  
  42.     string stemp = "insert into actor( actor_id , first_name , last_name,last_update )values(\"";  
  43.     string strsql;  
  44.     char str[10];  
  45.     if ( psql->SelectDB(sql , "sakila") )  
  46.     {     
  47.         while ( i != 100 )  
  48.         {  
  49.             sprintf( str , "%d" , i+index );  
  50.             strsql = stemp ;  
  51.             strsql +=  str;  
  52.             strsql += "\",\"0\",\"0\",\"0\")";  
  53.             if(!sql)  
  54.                 return 0;  
  55.   
  56.             if(!psql->Query(  sql ,strsql.c_str()  ))  
  57.             {  
  58.                 cout<<"add false"<<endl;  
  59.             }  
  60.   
  61.             ++i;  
  62.         }  
  63.   
  64.         psql->RelConnect(sql);  
  65.     }  
  66.     return 0;  
  67. }  




版本二:

一、头文件【存为: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()
{
   
    //暂时可以不实现。 因为查询失败时,已重新连接了。
}
















0 0
原创粉丝点击