iis服务器助手广告广告
返回顶部
首页 > 资讯 > 数据库 >基于MysqlConnector/C++的数据库连接池的实现是怎样的
  • 571
分享到

基于MysqlConnector/C++的数据库连接池的实现是怎样的

2024-04-02 19:04:59 571人浏览 泡泡鱼
摘要

基于MysqlConnector/c++的数据库连接池的实现是怎样的,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。1.连接池的介绍:1.1

基于MysqlConnector/c++数据库连接池的实现是怎样的,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。

1.连接池的介绍:

1.1应用背景:

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

1.2技术思想:

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

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

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

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

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

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

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

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

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

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

2.编程实现:

头文件(connection_pool.h):

[html] view
plaincopy

  1.    

  2. #ifndef_CONNECTION_POOL_H  

  3. #define _CONNECTION_POOL_H  

  4. #include<mysql_connection.h>

  5. #include<mysql_driver.h>

  6. #include<cppconn/exception.h>

  7. #include<cppconn/driver.h>

  8. #include<cppconn/connection.h>

  9. #include<cppconn/resultset.h>

  10. #include<cppconn/prepared_statement.h>

  11. #include<cppconn/statement.h>

  12. #include<pthread.h>

  13. #include<list>

  14. usingnamespace std;  

  15. usingnamespace sql;  


  16. classConnPool{  

  17. private:  

  18. intcurSize;//当前已建立的数据库连接数量  

  19. intmaxSize;//连接池中定义的最大数据库连接数  

  20. stringusername;  

  21. stringpassWord;  

  22. stringurl;  

  23. list<Connection*>connList;//连接池的容器队列  

  24. pthread_mutex_tlock;//线程  

  25. staticConnPool *connPool;  

  26. Driver*driver;  


  27. Connection*CreateConnection();//创建一个连接  

  28. voidInitConnection(int iInitialSize);//初始化数据库连接池  

  29. voidDestoryConnection(Connection *conn);//销毁数据库连接对象  

  30. voidDestoryConnPool();//销毁数据库连接池  

  31. ConnPool(stringurl,string user,string password,int maxSize);//构造方法  

  32. public:  

  33. ~ConnPool();  

  34. Connection*GetConnection();//获得数据库连接  

  35. voidReleaseConnection(Connection *conn);//将数据库连接放回到连接池的容器中  

  36. staticConnPool *GetInstance();//获取数据库连接池对象  

  37. };  

  38. #endif    

头文件中定义了一个容器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. #include "connection_pool.h"


  2. namespace ConnectMySQL {  


  3. //初始化连接池

  4. ConnPool *connpool = ConnPool::GetInstance();  


  5. void run() {  


  6.     Connection *con;  

  7.     Statement *state;  

  8.     ResultSet *result;  


  9.     // 从连接池中获取mysql连接

  10.     con = connpool->GetConnection();  


  11.     state = con->createStatement();  

  12.     state->execute("use holy");  


  13.     // 查询

  14.     result = state->executeQuery("select * from student where id < 1002");  


  15.     // 输出查询

  16.     while (result->next()) {  

  17.         int id = result->getInt("id");  

  18.         string name = result->getString("name");  

  19.         cout << id << " : " << name << endl;  

  20.     }  

  21.     delete state;  

  22.     connpool->ReleaseConnection(con);  

  23. }  

  24. }  


  25. int main(int arGC, char* argv[]) {  

  26.     ConnectMySQL::run();  

  27.     return 0;  

  28. }  

关于基于MysqlConnector/C++的数据库连接池的实现是怎样的问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注编程网数据库频道了解更多相关知识。

您可能感兴趣的文档:

--结束END--

本文标题: 基于MysqlConnector/C++的数据库连接池的实现是怎样的

本文链接: https://www.lsjlt.com/news/68759.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 基于MysqlConnector/C++的数据库连接池的实现是怎样的
    基于MysqlConnector/C++的数据库连接池的实现是怎样的,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。1.连接池的介绍:1.1...
    99+
    2022-10-19
  • 基于C++实现Mysql数据库连接池实例
    目录项目技术点项目意义项目实现Connection设计ConnectionPool设计项目复杂接口细节刨析项目技术点 C语言进行mysql数据库编程无锁单例基于STL队列加C++11新特性保证线程安全实现的生产者消费者模...
    99+
    2022-12-07
    C++数据库连接池 C++mysql连接池
  • C++怎么实现数据库连接池
    本文小编为大家详细介绍“C++怎么实现数据库连接池”,内容详细,步骤清晰,细节处理妥当,希望这篇“C++怎么实现数据库连接池”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。项目背景为了提高Mysql数据库的访问瓶颈...
    99+
    2023-07-05
  • 数据库连接池泄露后的思考是怎样的
    数据库连接池泄露后的思考是怎样的,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。 一:初步排查早上作为能效平台系统的使...
    99+
    2022-10-19
  • C#数据库连接池的创建
    本篇内容主要讲解“C#数据库连接池的创建”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C#数据库连接池的创建”吧!使用C#数据库连接池连接到数据库服务器通常由几个需要软长时间的步骤组成。必须建立...
    99+
    2023-06-18
  • 数据库连接池的原理?连接池使用什么数据结构实现?实现连接池?
    早期我们怎么进行数据库操作呢? 1、原理:一般来说,Java应用程序访问数据库的过程是: 加载数据库驱动程序; 通过jdbc建立数据库连接; 访问数据库,执行SQL语句; 断开数据库连接。 2、代码 1 //查询所有用户 ...
    99+
    2015-09-26
    数据库连接池的原理?连接池使用什么数据结构实现?实现连接池?
  • 数据库连接池dbcp的原理及配置是怎样的
    这篇文章将为大家详细讲解有关数据库连接池dbcp的原理及配置是怎样的,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。1. 简介DBCP(DataBa...
    99+
    2022-10-19
  • 如何用C++自己实现mysql数据库的连接池?
    为什么是mysql? 现在几乎所有的后台应用都要用到数据库,什么关系型的、非关系型的;正当关系的,不正当关系的;主流的和非主流的, 大到Oracle,小到sqlite,以及包括现在逐渐流行的基于物联网的时序数据库,比如涛思的TDengi...
    99+
    2015-05-02
    如何用C++自己实现mysql数据库的连接池?
  • SpringBoot 是怎样连接数据库的
    Spring Boot 是一款流行的 Java 开发框架,它可以轻松地连接各种类型的数据库,包括关系型数据库和非关系型数据库。本文将介绍 Spring Boot 是如何连接数据库的,包括其原理和代码示...
    99+
    2023-09-18
    数据库 spring boot java
  • Scala数据库连接池的简单实现
    在使用JDBC的时候,数据库据连接是非常宝贵的资源。为了复用这些资源,可以将连接保存在一个队列中。当需要的时候可以从队列中取出未使用的连接。如果没有可用连接,则可以在一定时间内等待,...
    99+
    2023-02-09
    Scala数据库连接池 Scala 连接池
  • 如何利用C++实现mysql数据库的连接池详解
    目录为什么是mysql? 为什么要搞资源池? mysql资源池实现的案例源码 头文件:MysqlPool.h实现文件:MysqlPool.cpp测试函数总结为什么是mysql? 现...
    99+
    2022-11-12
  • python数据库连接池中数据库连接池技术的优点是什么
    本篇文章给大家分享的是有关python数据库连接池中数据库连接池技术的优点是什么,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。昨天测试了一下开500个线程去请求数据库,不过这个...
    99+
    2023-06-17
  • SpringBoot 是怎样连接 MySql 数据库的
    Spring Boot 是一款流行的 Java 开发框架,它可以轻松地连接各种类型的数据库,包括关系型数据库和非关系型数据库。本文将介绍 Spring Boot 是如何连接数据库的,包括其原理和代码示例。 一、Spring Boot 连接...
    99+
    2023-08-18
    数据库 spring boot mysql
  • ADO.NET连接数据库使用是怎样的
    本篇文章为大家展示了ADO.NET连接数据库使用是怎样的,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。如果我们利用Command 对象所执行的命令是有传回数据的Select 叙述,此时Co...
    99+
    2023-06-17
  • Go语言配置数据库连接池的实现
    目录配置连接池SetMaxOpenConns方法SetMaxIdleConns方法SetConnMaxLifetime方法SetConnMaxIdleTime方法实操一波配置连...
    99+
    2022-06-07
    数据库连接 GO 连接 数据 数据库连接池 连接池 go语言 数据库
  • springboot项目整合druid数据库连接池的实现
    Druid连接池是阿里巴巴开源的数据库连接池项目,后来贡献给Apache开源; Druid的作用是负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再...
    99+
    2022-11-12
  • python3 实现mysql数据库连接池的示例代码
    dbutils封装文件传送门 DBUtils是一套Python数据库连接池包,并允许对非线程安全的数据库接口进行线程安全包装。DBUtils来自Webware for Python。...
    99+
    2022-11-12
  • 数据库连接配置的策略和实践是怎样的
    今天就跟大家聊聊有关数据库连接配置的策略和实践是怎样的,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。一 前言应用执行SQL请求完成的过程中,数据库连...
    99+
    2022-10-19
  • C# 连接本地数据库的实现示例
    目录使用环境 1. 安装MySQL2. 连接本地MySQL3. C# 连接本地MySQL使用环境  C#VSCodeM1 1. 安装MySQL 下载MySQL软件...
    99+
    2022-11-13
  • 数据库连接池的工作机制是什么
    数据库连接池的工作机制是为了提高数据库操作的性能和效率。它通过预先创建和管理一定数量的数据库连接,以避免频繁地创建、销毁连接,从而减...
    99+
    2023-09-15
    数据库
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作