From: http://blog.csdn.net/educast/article/details/14164097

1.连接池的介绍:

1.1应用背景:

一般的应用程序都会访问到数据库,在程序访问数据库的时候,每一次数据访问请求都必须经过下面几个步骤:建立数据库连接,打开数据库,对数据库中的数据进行操作,关闭数据库连接。而建立数据库连接和打开数据库是一件很消耗资源并且费时的工作,如果在系统中很频繁的发生这种数据库连接,必然会影响到系统的性能,甚至会导致系统的崩溃。

1.2技术思想:

在系统初始化阶段,建立一定数量的数据库连接对象(Connection),并将其存储在连接池中定义的容器中。当有数据库访问请求时,就从连接池中的这个容器中拿出一个连接;当容器中的连接已经用完,并且还没有达到系统定义的最大连接数时,可以再创建一个新的连接,当当前使用的连接数达到最大连接数时,就要等待其他访问请求将连接放回容器后才能使用。当使用完连接的时候,必须将连接放回容器中,这样不同的数据库访问请求就可以共享这些连接,通过重复使用这些已经建立的数据库连接,可以解决上节中说到的频繁建立连接的缺点,从而提高了系统的性能。

经过上述描述,我们可以归纳出数据库连接池的主要操作:

(1)首先建立一个数据库连接池对象

(2)初始化一定数量的数据库连接,放入连接池对象的容器中

(3)当有数据库访问请求时,直接从连接池的容器中得到一个连接,这里出现三种情况:

(a)当容器中的还有连接时,则返回给数据库访问请求者一个连接

(b)当容器中没有连接时,并且当前建立的连接数没有达到系统定义的最大连接数,则创建一个新的数据库连接。

(c)当容器中的没有连接并且当前建立的连接数达到系统定义的最大连接数,则当前访问数据库请求就要等待其他访问请求释放连接。

(4)当数据库访问完成后,应该将连接放回连接池的容器中。

(5)当服务停止时,需要先释放数据库连接池中的所有数据库连接,然后再释放数据库连接池对象。

2.编程实现:

头文件(connection_pool.h):

[html] view plaincopy
  1. /*
  2. *File: connection_pool.h
  3. *Author: csc
  4. */
  5. #ifndef_CONNECTION_POOL_H
  6. #define _CONNECTION_POOL_H
  7. #include<mysql_connection.h>
  8. #include<mysql_driver.h>
  9. #include<cppconn/exception.h>
  10. #include<cppconn/driver.h>
  11. #include<cppconn/connection.h>
  12. #include<cppconn/resultset.h>
  13. #include<cppconn/prepared_statement.h>
  14. #include<cppconn/statement.h>
  15. #include<pthread.h>
  16. #include<list>
  17. usingnamespace std;
  18. usingnamespace sql;
  19. classConnPool{
  20. private:
  21. intcurSize;//当前已建立的数据库连接数量
  22. intmaxSize;//连接池中定义的最大数据库连接数
  23. stringusername;
  24. stringpassword;
  25. stringurl;
  26. list<Connection*>connList;//连接池的容器队列
  27. pthread_mutex_tlock;//线程锁
  28. staticConnPool *connPool;
  29. Driver*driver;
  30. Connection*CreateConnection();//创建一个连接
  31. voidInitConnection(int iInitialSize);//初始化数据库连接池
  32. voidDestoryConnection(Connection *conn);//销毁数据库连接对象
  33. voidDestoryConnPool();//销毁数据库连接池
  34. ConnPool(stringurl,string user,string password,int maxSize);//构造方法
  35. public:
  36. ~ConnPool();
  37. Connection*GetConnection();//获得数据库连接
  38. voidReleaseConnection(Connection *conn);//将数据库连接放回到连接池的容器中
  39. staticConnPool *GetInstance();//获取数据库连接池对象
  40. };
  41. #endif  /*_CONNECTION_POOL_H */

头文件中定义了一个容器connList,里面存放了很多个未使用的连接;在对容器内的连接进行操作的时候,需要加锁来保证程序的安全性,所以头文件中定义了一个lock,通过使用lock保证了同一时间只有一个线程对容器进行操作。

连接池类要统一管理整个应用程序中的连接,所以在整个系统中只需要维护一个连接池对象,试想:如果系统中定义了多个连接池对象,那么每一个对象都可以建立maxSize个连接,这样就失去了创建连接池的初衷,破环了通过连接池统一管理系统中连接的思想。所以这里使用单例模式编写连接池类,单例模式确保一个类只有一个实例,自己进行实例化并且向整个系统提供这个实例。在头文件中,我们定义了一个静态的连接池对象connPool,连接池类提供一个静态的公共方法GetInstance(),外部程序通过调用这个方法来获得连接池对象。并且将连接池类的构造函数定义为私有的,外部的应用程序不能够通过new来实例化连接池类,只能通过GetInstance()方法获得连接池对象;在GetInstance()方法中需要判断连接池类中定义的connPool是否为NULL,若为NULL则调用私有构造函数实例化connPool,若不为空,则直接返回connPool。这样就实现了连接池类的单例模式,从而保证了系统运行过程中只建立一个连接池类的实例对象。

在实例化连接池类的对象时,要对连接池做一些初始化的操作,即建立一定数量的数据库连接。程序中通过InitConnection(intiInitialSize)方法对连接池进行初始化,创建iInitialSize个连接,并且将这些连接放在连接池中的容器connList中,每新建一个连接,curSize就加1。当有数据库访问请求时,需要从连接池中获取一个连接,通过GetConnection()方法实现:首先判断容器中是否还有连接,如果有,则拿出容器中的第一个连接,并且将该连接移出容器;获得的连接要进行判断,如果连接已经关闭,则回收该连接的内存空间,并且重新创建一个连接;然后判断新创建的连接是否为空,如果为空,则说明当前已经建立连接的数量并不是curSize个,而是(curSize-1)个(应该除去这个空连接)。如果容器中已经没有连接了,则要判断当前的curSize值是否已经达到规定的maxSize,如果没有小于maxSize,将建立一个新的连接(++curSize)。如果超过maxSize则等待其他数据库访问请求释放数据库连接。

连接使用完以后,需要将连接放回连接池中,通过ReleaseConnection(sql::Connection* conn)方法实现,它的实现非常简单,就是将传进来的connection连接添加到连接池的容器中。

当需要回收连接池的内存空间时,需要先回收连接池中所有连接的内存空间,然后再释放连接池对象的内存空间。

实现数据库连接池主要的步骤就是上述这些,具体的代码实现如下所示:

[cpp] view plaincopy
  1. #include<stdexcept>
  2. #include<exception>
  3. #include<stdio.h>
  4. #include"connection_pool.h"
  5. usingnamespace std;
  6. usingnamespace sql;
  7. ConnPool*ConnPool::connPool=NULL;
  8. //连接池的构造函数
  9. ConnPool::ConnPool(stringurl, string userName,string password, int maxSize)
  10. {
  11. this->maxSize=maxSize;
  12. this->curSize=0;
  13. this->username=userName;
  14. this->password=password;
  15. this->url=url;
  16. try{
  17. this->driver=sql::mysql::get_driver_instance();
  18. }
  19. catch(sql::SQLException&e)
  20. {
  21. perror("驱动连接出错;\n");
  22. }
  23. catch(std::runtime_error&e)
  24. {
  25. perror("运行出错了\n");
  26. }
  27. this->InitConnection(maxSize/2);
  28. }
  29. //获取连接池对象,单例模式
  30. ConnPool*ConnPool::GetInstance(){
  31. if(connPool==NULL)
  32. {
  33. connPool=newConnPool("tcp://127.0.0.1:3306","root","root",50);
  34. }
  35. returnconnPool;
  36. }
  37. //初始化连接池,创建最大连接数的一半连接数量
  38. voidConnPool::InitConnection(int iInitialSize)
  39. {
  40. Connection*conn;
  41. pthread_mutex_lock(&lock);
  42. for(inti=0;i<iInitialSize;i++)
  43. {
  44. conn=this->CreateConnection();
  45. if(conn){
  46. connList.push_back(conn);
  47. ++(this->curSize);
  48. }
  49. else
  50. {
  51. perror("创建CONNECTION出错");
  52. }
  53. }
  54. pthread_mutex_unlock(&lock);
  55. }
  56. //创建连接,返回一个Connection
  57. Connection*ConnPool::CreateConnection(){
  58. Connection*conn;
  59. try{
  60. conn=driver->connect(this->url,this->username,this->password);//建立连接
  61. returnconn;
  62. }
  63. catch(sql::SQLException&e)
  64. {
  65. perror("创建连接出错");
  66. returnNULL;
  67. }
  68. catch(std::runtime_error&e)
  69. {
  70. perror("运行时出错");
  71. returnNULL;
  72. }
  73. }
  74. //在连接池中获得一个连接
  75. Connection*ConnPool::GetConnection(){
  76. Connection*con;
  77. pthread_mutex_lock(&lock);
  78. if(connList.size()>0)//连接池容器中还有连接
  79. {
  80. con=connList.front();//得到第一个连接
  81. connList.pop_front();//移除第一个连接
  82. if(con->isClosed())//如果连接已经被关闭,删除后重新建立一个
  83. {
  84. deletecon;
  85. con=this->CreateConnection();
  86. }
  87. //如果连接为空,则创建连接出错
  88. if(con==NULL)
  89. {
  90. --curSize;
  91. }
  92. pthread_mutex_unlock(&lock);
  93. returncon;
  94. }
  95. else{
  96. if(curSize< maxSize){//还可以创建新的连接
  97. con= this->CreateConnection();
  98. if(con){
  99. ++curSize;
  100. pthread_mutex_unlock(&lock);
  101. returncon;
  102. }
  103. else{
  104. pthread_mutex_unlock(&lock);
  105. returnNULL;
  106. }
  107. }
  108. else{//建立的连接数已经达到maxSize
  109. pthread_mutex_unlock(&lock);
  110. returnNULL;
  111. }
  112. }
  113. }
  114. //回收数据库连接
  115. voidConnPool::ReleaseConnection(sql::Connection * conn){
  116. if(conn){
  117. pthread_mutex_lock(&lock);
  118. connList.push_back(conn);
  119. pthread_mutex_unlock(&lock);
  120. }
  121. }
  122. //连接池的析构函数
  123. ConnPool::~ConnPool()
  124. {
  125. this->DestoryConnPool();
  126. }
  127. //销毁连接池,首先要先销毁连接池的中连接
  128. voidConnPool::DestoryConnPool(){
  129. list<Connection*>::iterator icon;
  130. pthread_mutex_lock(&lock);
  131. for(icon=connList.begin();icon!=connList.end();++icon)
  132. {
  133. this->DestoryConnection(*icon);//销毁连接池中的连接
  134. }
  135. curSize=0;
  136. connList.clear();//清空连接池中的连接
  137. pthread_mutex_unlock(&lock);
  138. }
  139. //销毁一个连接
  140. voidConnPool::DestoryConnection(Connection* conn)
  141. {
  142. if(conn)
  143. {
  144. try{
  145. conn->close();
  146. }
  147. catch(sql::SQLException&e)
  148. {
  149. perror(e.what());
  150. }
  151. catch(std::exception&e)
  152. {
  153. perror(e.what());
  154. }
  155. deleteconn;
  156. }
  157. }
[cpp] view plaincopyprint?
  1. /*
  2. * main.cpp
  3. *
  4. *  Created on: 2013-3-26
  5. *      Author: holy
  6. */
  7. #include "connection_pool.h"
  8. namespace ConnectMySQL {
  9. //初始化连接池
  10. ConnPool *connpool = ConnPool::GetInstance();
  11. void run() {
  12. Connection *con;
  13. Statement *state;
  14. ResultSet *result;
  15. // 从连接池中获取mysql连接
  16. con = connpool->GetConnection();
  17. state = con->createStatement();
  18. state->execute("use holy");
  19. // 查询
  20. result = state->executeQuery("select * from student where id < 1002");
  21. // 输出查询
  22. while (result->next()) {
  23. int id = result->getInt("id");
  24. string name = result->getString("name");
  25. cout << id << " : " << name << endl;
  26. }
  27. delete state;
  28. connpool->ReleaseConnection(con);
  29. }
  30. }
  31. int main(int argc, char* argv[]) {
  32. ConnectMySQL::run();
  33. return 0;
  34. }

基于MysqlConnector/C++的数据库连接池的实现相关推荐

  1. 基于tomcat5.5的数据库连接池环境设置

    1.安装tomcat5.5的admin package tomcat5.5版本中的admin没有默认安装,先下载admin package jakarta-tomcat-5.5.9-admin.zip ...

  2. 基于tomcat5.5的数据库连接池环境设置(省的以后找系列)

    1.安装tomcat5.5的admin package tomcat5.5版本中的admin没有默认安装,先下载admin package jakarta-tomcat-5.5.9-admin.zip ...

  3. 基于DBUtils实现数据库连接池

    小知识: 1.子类继承父类的三种方式 class Dog(Animal): #子类 派生类def __init__(self,name,breed, life_value,aggr):# Animal ...

  4. python数据库连接池工具类_Python数据库连接池DBUtils

    DBUtils简介 DBUtils是Python的一个用于实现数据库连接池的模块. 此连接池有两种连接模式: 模式一:为每个线程创建一个连接,线程即使调用了close方法,也不会关闭,只是把连接重新放 ...

  5. mysql连接池_基于Swoole的通用连接池 - 数据库连接池(life)

    open-smf/connection-pool 是一个基于Swoole的通用连接池,常被用作数据库连接池. 依赖 依赖版本PHP>=7.0.0Swoole>=4.2.9Recommend ...

  6. 基于JDBC的数据库连接池技术研究与应用

    引言 近年来,随着Internet/Intranet建网技术的飞速发展和在世界范围内的迅速普及,计算机 应用程序已从传统的桌面应用转到Web应用.基于B/S(Browser/Server)架构的3层开 ...

  7. swoole mysql 连接池_基于Swoole的通用连接池 - 数据库连接池

    连接池 open-smf/connection-pool 是一个基于Swoole的通用连接池,常被用作数据库连接池. 依赖 依赖 版本 >=7.0.0 >=4.2.9 Recommend ...

  8. JDBC工具类,基于C3P0的数据库连接池,提供获取连接池、获取连接对象、释放资源和封装事务操作的方法...

    /**  *  * JDBC工具类,基于C3P0数据库连接池的实现  *  * @author 周瑜  * @2018年5月7日 下午2:13:20  */ public final class JD ...

  9. 基于UniDac的数据库连接池

    上篇提到了在XE-XE6下安装UniDac.这篇,就基于UniDac,实现一个简单的数据库连接池. 文本的目录: 1.简单描述连接池实现的好处和原理: 2.连接池实现代码: 3.给出使用连接池的Dem ...

最新文章

  1. Qt控件与按钮颜色透明
  2. 强化学习(五)—— AlphaGo与Alpha Zero
  3. log4j2.xml
  4. 学php要先学css吗,学PHP是不是就必须学htmlcssjs
  5. 基于JAVA+SpringMVC+Mybatis+MYSQL的学生公寓管理系统
  6. 讲的是关于提高网站速度的内容|转自csdn
  7. 机器学习之网格搜索(GridSearch)及参数说明,实例演示
  8. Github使用: 无法打开github网页
  9. 8、(八)外汇基础篇之外汇期权交易
  10. 常有不规则动词的过去式和过去分词…
  11. Pr零基础入门指南笔记二
  12. 004-中国五个城市PM 2.5数据分析
  13. Transformer BEV perception
  14. python 协程加多线程下载asyncio、ThreadPoolExecutor
  15. 【智慧家科教2023新春首训】东方昱老师畅谈新发展之路:前途是光明的 未来是可期的
  16. 电脑是否存在内存泄漏_如何避免内存泄露
  17. 线性代数---魏福义版 第一章习题答案
  18. 困扰一周的配环境问题——RTX3090+CUDA11.1
  19. m基于强化学习的PID控制器simulink仿真,对比PI控制器和变结构PI控制器
  20. 高德拉特:约束理论(TOC)和最优生产技术(OPT)相关

热门文章

  1. jboss-AS目录结构了解(资料摘取)
  2. TortoiseGit + GitHub 快速上手指南
  3. winform 与WPF
  4. 一个怎样得到treeView值的小例子
  5. java 分裂数字_分裂的补充:超越数字,打印物理可视化
  6. 5886. 如果相邻两个颜色均相同则删除当前颜色
  7. leetcode 692. 前K个高频单词
  8. 深入理解InnoDB(7)—系统表空间
  9. leetcode 73. 矩阵置零
  10. python3:面向对象(多态和继承、方法重载及模块)