一、基础知识
- 数据库连接池:池是一组资源的集合,这组资源在服务器启动之初就被创建并初始化。数据库连接池就是专门处理数据库连接的资源,当客户发起请求时,就从池中获取资源;完成任务后,就将其放回资源池。整个过程无需使用系统调用动态分配或释放资源。
- 数据库访问流程:先系统创建数据库连接,完成数据库操作,然后断开数据库连接;
二、代码解析
1. 单例模式创建
class connection_pool
{
public:
MYSQL *GetConnection();
bool ReleaseConnection(MYSQL *conn);
int GetFreeConn();
void DestroyPool();
static connection_pool *GetInstance();
void init(string url, string User, string PassWord, string DataBaseName, int Port, int MaxConn, int close_log);
private:
connection_pool();
~connection_pool();
int m_MaxConn;
int m_CurConn;
int m_FreeConn;
locker lock;
list<MYSQL *> connList;
sem reserve;
public:
string m_url;
string m_Port;
string m_User;
string m_PassWord;
string m_DatabaseName;
int m_close_log;
};
2. 连接池初始化
connection_pool::connection_pool()
{
m_CurConn = 0;
m_FreeConn = 0;
}
void connection_pool::init(string url, string User, string PassWord, string DBName, int Port, int MaxConn, int close_log)
{
m_url = url;
m_Port = Port;
m_User = User;
m_PassWord = PassWord;
m_DatabaseName = DBName;
m_close_log = close_log;
for (int i = 0; i < MaxConn; i++)
{
MYSQL *con = NULL;
con = mysql_init(con);
if (con == NULL)
{
LOG_ERROR("MySQL Error");
exit(1);
}
con = mysql_real_connect(con, url.c_str(), User.c_str(), PassWord.c_str(), DBName.c_str(), Port, NULL, 0);
if (con == NULL)
{
LOG_ERROR("MySQL Error");
exit(1);
}
connList.push_back(con);
++m_FreeConn;
}
reserve = sem(m_FreeConn);
m_MaxConn = m_FreeConn;
}
connectionRAII::~connectionRAII()
{
poolRAII->ReleaseConnection(conRAII);
}
3. 获取和释放连接
MYSQL *connection_pool::GetConnection()
{
MYSQL *con = NULL;
if (0 == connList.size())
return NULL;
reserve.wait();
lock.lock();
con = connList.front();
connList.pop_front();
--m_FreeConn;
++m_CurConn;
lock.unlock();
return con;
}
bool connection_pool::ReleaseConnection(MYSQL *con)
{
if (NULL == con)
return false;
lock.lock();
connList.push_back(con);
++m_FreeConn;
--m_CurConn;
lock.unlock();
reserve.post();
return true;
}
4. 销毁线程池
void connection_pool::DestroyPool()
{
lock.lock();
if (connList.size() > 0)
{
list<MYSQL *>::iterator it;
for (it = connList.begin(); it != connList.end(); ++it)
{
MYSQL *con = *it;
mysql_close(con);
}
m_CurConn = 0;
m_FreeConn = 0;
connList.clear();
}
lock.unlock();
}
5. RAII 机制释放数据库连接
class connectionRAII
{
public:
connectionRAII(MYSQL **con, connection_pool *connPool);
~connectionRAII();
private:
MYSQL *conRAII;
connection_pool *poolRAII;
};
connectionRAII::connectionRAII(MYSQL **SQL, connection_pool *connPool)
{
*SQL = connPool->GetConnection();
conRAII = *SQL;
poolRAII = connPool;
}
connectionRAII::~connectionRAII()
{
poolRAII->ReleaseConnection(conRAII);
}
参考文献
[1] 最新版Web服务器项目详解 - 11 数据库连接池