实现数据库连接池

文章目录
  1. 1. 单例模式创建连接池
  2. 2. 初始化
  3. 3. 获取&释放连接
  4. 4. 销毁连接池
  5. 5. RAII 释放数据库连接
  6. 6. 参考资料

数据库连接池采用单例模式创建,使用 RAII 机制释放数据库连接。

单例模式创建连接池

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class connection_pool
{
public:
//局部静态变量单例模式
static connection_pool *GetInstance();

private:
connection_pool();
~connection_pool();
}

connection_pool *connection_pool::GetInstance()
{
static connection_pool connPool;
return &connPool;
}

初始化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
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;
}

获取&释放连接

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
//当有请求时,从数据库连接池中返回一个可用连接,更新使用和空闲连接数
MYSQL *connection_pool::GetConnection()
{
MYSQL *con = NULL;

if (0 == connList.size())
return NULL;

reserve.wait(); // 取出连接,信号量原子 -1, 为0则等待

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(); // 释放连接 原子+1
return true;
}

销毁连接池

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//销毁数据库连接池
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();
}

RAII 释放数据库连接

1
2
3
4
5
6
7
8
9
10
11
class connectionRAII{

public:
//双指针对MYSQL *con修改
connectionRAII(MYSQL **con, connection_pool *connPool);
~connectionRAII();

private:
MYSQL *conRAII;
connection_pool *poolRAII;
};

不直接调用获取和释放连接的接口,将其封装起来,通过RAII机制进行获取和释放。

1
2
3
4
5
6
7
8
9
10
connectionRAII::connectionRAII(MYSQL **SQL, connection_pool *connPool){
*SQL = connPool->GetConnection();

conRAII = *SQL;
poolRAII = connPool;
}

connectionRAII::~connectionRAII(){
poolRAII->ReleaseConnection(conRAII);
}

参考资料