aurain
技术文摘
posts - 137,  comments - 268,  trackbacks - 0

在有大量节点访问的数据库设计中,经常要使用到连接池来管理所有的连接.
一般方法是:建立两个连接句柄队列,空闲的等待使用的队列和正在使用的队列.
当要查询时先从空闲队列中获取一个句柄,插入到正在使用的队列,再用这个句柄做数据库操作,完毕后一定要从使用队列中删除,再插入到空闲队列.
代码如下:
MySQLMan.h
 // MySQLMan.h: interface for the CMySQLMan class.
//
//////////////////////////////////////////////////////////////////////
#include <mysql.h>
#pragma comment(lib,"libmySQL.lib")

#include <list>

typedef std::list<MYSQL *> CONNECTION_HANDLE_LIST;
typedef std::list<MYSQL *>::iterator ITER_CONNECTION_HANDLE_LIST;

#define CONNECTION_NUM 10 //同时打开的连接数

class CMySQLMan 
{
public:
 CMySQLMan();
 CMySQLMan(const char *host, const char *user, const char *password, const char *db, unsigned int port=3306);
 virtual ~CMySQLMan();
 
public:
 bool ConnectDB();      //连接数据库
 MYSQL_RES* SelectRecord(const char *szSql); //选择记录,返回结果集
 bool SelectDB(const char *szDB);  //选择数据库
 bool UpdateRecord(const char *szSql); //更新记录
 bool InsertRecord(const char *szSql); //插入记录
 bool DelRecord(const char *szSql);  //删除记录

 BOOL IsEnd(MYSQL_RES *myquery);       //是否最后
 void SeekData(MYSQL_RES *myquery, int offset);    //查找指定数据
 void FreeRecord(MYSQL_RES *myquery);      //释放结果集
 unsigned int GetFieldNum(MYSQL_RES *myquery);    //得到字段数
 MYSQL_ROW GetRecord(MYSQL_RES *myquery);     //得到结果(一个记录)
 my_ulonglong GetRowNum(MYSQL_RES *myquery);    //得到记录数
 char* OutErrors(MYSQL* pMySql);      //输出错误信息

 char* GetState();      //服务器状态
 char* GetServerInfo();     //服务器信息
 int GetProtocolInfo();     //协议信息
 char* GetHostInfo();     //主机信息
 char* GetClientInfo();     //客户机信息
 char* GetFieldName(MYSQL_RES *myquery, int FieldNum);  //字段名

 bool LockTable(const char *TableName, const char *Priority); //对特定表加锁
 bool UnlockTable();      //解锁
 bool SetCharset();
 //int CreateDB(char *db);    //创建数据库,返回错误信息
 //int DropDB(char *db);     //删除数据库,返回错误信息

 MYSQL* GetIdleMySql();     //提取一个空闲句柄供使用
 void SetIdleMysql(MYSQL* pMySql);  //从使用队列中释放一个使用完毕的句柄,插入到空闲队列

public:
 //MYSQL  m_mysql;      //数据库连接句柄
 MYSQL_ROW m_row;       //记录集(单行)
 MYSQL_FIELD *m_field;      //字段信息(结构体)

 //创建两个队列
 CONNECTION_HANDLE_LIST m_lsBusyList;                //正在使用的连接句柄
 CONNECTION_HANDLE_LIST m_lsIdleList;                //未使用的连接句柄

 CRITICAL_SECTION m_csList;

public:
 char m_host[20];   //主机
 char m_user[20];   //用户名
 char m_password[20];  //密码
 char m_db[20];    //数据库名
 unsigned int m_port;  //端口
};

MySQLMan.cpp
// MySQLMan.cpp: implementation of the MySQLMan class.
//
//////////////////////////////////////////////////////////////////////
#include "StdAfx.h"
#include "MySQLMan.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CMySQLMan::CMySQLMan()
{
 
}

CMySQLMan::CMySQLMan(const char *host, const char *user, const char *password, const char *db, unsigned int port/* =3306 */)
{
 strcpy(m_host, host);
 strcpy(m_user, user);
 strcpy(m_password, password);
 strcpy(m_db, db);
 m_port = port;

 InitializeCriticalSection(&m_csList);
}

CMySQLMan::~CMySQLMan()
{
 for (ITER_CONNECTION_HANDLE_LIST iter=m_lsBusyList.begin(); iter != m_lsBusyList.end(); iter++)
 {
  mysql_close((*iter));
 }

 for (ITER_CONNECTION_HANDLE_LIST iter=m_lsIdleList.begin(); iter != m_lsIdleList.end(); iter++)
 {
  mysql_close((*iter));
 }

 DeleteCriticalSection(&m_csList);
}

bool CMySQLMan::ConnectDB()
{
 //同时打开CONNECTION_NUM个连接
 try
 {
  for (int i=0; i<CONNECTION_NUM; ++i)
  {
   MYSQL *pMySql = mysql_init((MYSQL*)NULL);
   if (pMySql != NULL)
   {
    if (!mysql_real_connect(pMySql,m_host,m_user,m_password,m_db,m_port,NULL,0))
    {
     OutErrors(pMySql);
     return false;
    }
    m_lsIdleList.push_back(pMySql);
   }
  }
 }
 catch (...)
 {
  return false;
 }
 return true;
}

MYSQL* CMySQLMan::GetIdleMySql()
{
 MYSQL* pMySql = NULL;
 EnterCriticalSection(&m_csList);
 if (m_lsIdleList.size() > 0)
 {
  pMySql = m_lsIdleList.front();
  m_lsIdleList.pop_front();
  m_lsBusyList.push_back(pMySql);
 }
 else
 {
  pMySql = NULL;
 }
 LeaveCriticalSection(&m_csList);

 return pMySql;
}

void CMySQLMan::SetIdleMysql(MYSQL* pMySql)
{
 EnterCriticalSection(&m_csList);
 m_lsBusyList.remove(pMySql);
 m_lsIdleList.push_back(pMySql);
 LeaveCriticalSection(&m_csList);
}

MYSQL_RES* CMySQLMan::SelectRecord(const char *szSql)
{
 MYSQL *pMySql = GetIdleMySql();
 if (pMySql == NULL)
 {
  return NULL;
 }
 if(mysql_query(pMySql,szSql))
  return NULL;
 MYSQL_RES *myquery = NULL;
 myquery = mysql_store_result(pMySql);
 SetIdleMysql(pMySql);

 return myquery;
}

bool CMySQLMan::InsertRecord(const char *szSql)
{
 bool bRet = false;
 MYSQL *pMySql = GetIdleMySql();
 if (pMySql == NULL)
 {
  return false;
 }
 if(mysql_query(pMySql,szSql))
 {
  bRet = true;
 }
 SetIdleMysql(pMySql);

 return bRet;
}

bool CMySQLMan::UpdateRecord(const char *szSql)
{
 bool bRet = false;
 MYSQL *pMySql = GetIdleMySql();
 if (pMySql == NULL)
 {
  return false;
 }
 if(mysql_query(pMySql,szSql))
 {
  bRet = true;
 }
 SetIdleMysql(pMySql);

 return bRet;
}

bool CMySQLMan::DelRecord(const char *szSql)
{
 bool bRet = false;
 MYSQL *pMySql = GetIdleMySql();
 if (pMySql == NULL)
 {
  return false;
 }
 if(mysql_query(pMySql,szSql))
 {
  bRet = true;
 }
 SetIdleMysql(pMySql);

 return bRet;
}

bool CMySQLMan::SelectDB(const char *szDB)
{
 bool bRet = false;
 MYSQL *pMySql = GetIdleMySql();
 if (pMySql == NULL)
 {
  return false;
 }
 if (mysql_select_db(pMySql,szDB))
  bRet = false; 
 else
  bRet = true;
 SetIdleMysql(pMySql);

 return bRet;
}

my_ulonglong CMySQLMan::GetRowNum(MYSQL_RES *myquery)
{
 return mysql_num_rows(myquery);
}

MYSQL_ROW CMySQLMan::GetRecord(MYSQL_RES *myquery)
{
 m_row = mysql_fetch_row(myquery);

 return m_row;
}

unsigned int CMySQLMan::GetFieldNum(MYSQL_RES *myquery)
{
 return mysql_num_fields(myquery);
}

void CMySQLMan::FreeRecord(MYSQL_RES *myquery)
{
 mysql_free_result(myquery);
}

//int CMySQLMan::CreateDB(char *db)
//{
// return mysql_create_db(&m_mysql,db);
//}

void CMySQLMan::SeekData(MYSQL_RES *myquery, int offset)
{
 mysql_data_seek(myquery,offset);
}


char * CMySQLMan::OutErrors(MYSQL *pMySql)
{
 return const_cast<char *>(mysql_error(pMySql));
}

BOOL CMySQLMan::IsEnd(MYSQL_RES *myquery)
{
 return mysql_eof(myquery);
}

char* CMySQLMan::GetFieldName(MYSQL_RES *myquery, int FieldNum)
{
 m_field = mysql_fetch_field_direct(myquery, FieldNum);

 return m_field->name;
}

char * CMySQLMan::GetClientInfo()
{
 return const_cast<char *>(mysql_get_client_info());
}

char* CMySQLMan::GetHostInfo()
{
 MYSQL *pMySql = GetIdleMySql();
 if (pMySql == NULL)
 {
  return NULL;
 }
 return const_cast<char *>(mysql_get_host_info(pMySql));
}

int CMySQLMan::GetProtocolInfo()
{
 int iRet = 0;
 MYSQL *pMySql = GetIdleMySql();
 if (pMySql == NULL)
 {
  return NULL;
 }
 iRet = mysql_get_proto_info(pMySql);
 SetIdleMysql(pMySql);

 return iRet;
}

char* CMySQLMan::GetServerInfo()
{
 static char szRet[1024];
 MYSQL *pMySql = GetIdleMySql();
 if (pMySql == NULL)
 {
  return NULL;
 }
 _tcscpy(szRet, const_cast<char *>(mysql_get_server_info(pMySql)));
 SetIdleMysql(pMySql);

 return szRet;
}

char* CMySQLMan::GetState()
{
 MYSQL *pMySql = GetIdleMySql();
 if (pMySql == NULL)
 {
  return NULL;
 }
 static char szRet[1024];
 _tcscpy(szRet,const_cast<char *>(mysql_stat(pMySql)));
 SetIdleMysql(pMySql);

 return szRet;
}

bool CMySQLMan::SetCharset()
{
 bool bRet = false;
 char szSql[50];
 strcpy(szSql, "set names gb2312");
 MYSQL *pMySql = GetIdleMySql();
 if (pMySql == NULL)
 {
  return false;
 }
 if (mysql_query(pMySql, szSql))
  bRet = true;
 SetIdleMysql(pMySql);

 return bRet;
}

//LOCK TABLES tbl1 READ, tbl2 WRITE
bool CMySQLMan::LockTable(const char *TableName, const char *Priority)
{
 bool bRet = false;
 char szSql[50];
 sprintf(szSql, "LOCK TABLES %s %s", TableName, Priority);
 MYSQL *pMySql = GetIdleMySql();
 if (pMySql == NULL)
 {
  return false;
 }
 if (mysql_query(pMySql, szSql))
  bRet = true;
 SetIdleMysql(pMySql);

 return bRet;
}

bool CMySQLMan::UnlockTable()
{
 bool bRet = false;
 MYSQL *pMySql = GetIdleMySql();
 if (pMySql == NULL)
 {
  return false;
 }
 if(mysql_query(pMySql,"UNLOCK TABLES"))
  bRet = true;
 SetIdleMysql(pMySql);

 return bRet;

}

 

posted on 2008-02-21 15:10 阅读(4512) 评论(1)  编辑 收藏 引用 所属分类: socket编程

FeedBack:
# re: 在vc中通过连接池操作mysql(api方式),附c++访问mysql的封装类
2008-09-19 13:16 | Zech
mysql++  回复  更多评论
  

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理



<2008年2月>
272829303112
3456789
10111213141516
17181920212223
2425262728291
2345678

常用链接

留言簿(17)

随笔分类(138)

随笔档案(137)

网络开发

最新随笔

搜索

  •  

积分与排名

  • 积分 - 493566
  • 排名 - 36

最新随笔

最新评论

阅读排行榜

评论排行榜