c++ 实现数据库连接池
来源:互联网 发布:java web 2年水平 编辑:程序博客网 时间:2024/05/17 22:22
c++ 实现数据库连接池
自己尝试用c++ 新标准实现了数据库连接池,代码简化了很多。
思路:
将数据库的连接当作一个对象添加进list队列中,在连接池创建的时候就建立好队列,并添加自定义大小的连接对象,连接对象用智能指针来管理(现代c++中不应该出现delete语句),避免类似内存泄漏等内存问题,智能指针上用lambda表达式注册了delete删除函数来释放连接资源,及时归还,(其中用了std::move来转移list中的对象所有权到函数里的临时智能指针对象,当离开作用域时,自动释放。)
关于数据库连接池介绍可以看下面两篇文章:
浅析数据库连接池(一)
浅析数据库连接池(二)
代码:
mysql_connect.h
#ifndef _MYSQL_CONNECTION_#define _MYSQL_CONNECTION_//c++#include <iostream>#include <string>#include <list>#include <memory>#include <functional>//mysql driver#include <mysql_driver.h>#include <mysql_connection.h>//mysql execute#include <cppconn/driver.h>#include <cppconn/statement.h>#include <cppconn/prepared_statement.h>#include <cppconn/resultset.h>#include <exception>//thread mutex #include <mutex>using namespace sql;using delFunc = std::function<void(Connection*)>;class ConnectionPool{ public: //获取数据库连接池对象 static单例模式 static ConnectionPool* getInstance(); //得到一条连接 auto getConnect()->std::shared_ptr<Connection>; //归还一条连接 auto retConnect(std::shared_ptr<Connection> &ret)->void; ~ConnectionPool(); private: ConnectionPool(std::string name, std::string pwd, std::string nurl, int maxSize); //初始化连接池 auto initConnectPool(int initialSize)->void; //毁坏连接池 auto destoryPool()->void; //destory one connection auto destoryOneConn()->void; //扩大数据库连接池 auto expandPool(int size)->void; //缩小数据库连接池 auto reducePool(int size)->void; //add conn auto addConn(int size)->void; public: //get size auto getPoolSize()->int; private: std::string username; //帐号 std::string password; //密码 std::string url; //连接url int poolSize; //pool size //存放所有连接 std::list<std::shared_ptr<Connection>> conList; static ConnectionPool *pool;//连接池对象 std::mutex lock;//锁 Driver *driver;//mysql driver};#endif
mysql_connect.cpp
#include <stdio.h>#include <stdlib.h>#include <assert.h>#include "mysql_connect.h"ConnectionPool*ConnectionPool::pool = nullptr;//private//构造函数ConnectionPool::ConnectionPool(std::string name, std::string pwd, std::string nurl, int maxSize): username(name), password(pwd), url(nurl), poolSize(maxSize){ //得到mysql驱动 driver = get_driver_instance(); //开始初始化大小一半 initConnectPool(poolSize/2);}//析构函数ConnectionPool::~ConnectionPool(){ destoryPool();}//得到连接池大小intConnectionPool::getPoolSize(){ return conList.size();}//增加连接voidConnectionPool::addConn(int size){ for(int i = 0; i < size; ++i) { //创建连接 Connection *conn = driver->connect(url, username, password); std::shared_ptr<Connection> sp(conn, [](Connection *conn){ delete conn; }); conList.push_back(std::move(sp)); }}//初始化连接池voidConnectionPool::initConnectPool(int initialSize){ //加锁,增添一个连接 std::lock_guard<std::mutex> locker(lock); addConn(initialSize);}//销毁一个连接voidConnectionPool::destoryOneConn(){ //智能指针加std::move转移一个连接的“所有权”,当出作用域时,自动调用关闭connect std::shared_ptr<Connection> &&sp = std::move(conList.front()); sp->close(); --poolSize;}//销毁整个连接池void ConnectionPool::destoryPool(){ for(auto &conn : conList) { //依次转移所有权,出作用域时,关闭连接,出作用域时智能指针自动释放 std::shared_ptr<Connection> &&sp = std::move(conList.front()); sp->close(); }}//扩大连接池voidConnectionPool::expandPool(int size){ std::lock_guard<std::mutex> locker(lock); addConn(size); poolSize += size;}//缩小连接池voidConnectionPool::reducePool(int size){ std::lock_guard<std::mutex> locker(lock); //减小的大小不能超过存储的大小 if(size > poolSize) { return; } for(int i = 0; i < size; i++) { //sp point new object, old object release destoryOneConn(); } poolSize -= size;}//public//得到连接池实例ConnectionPool*ConnectionPool::getInstance(){ if(pool == nullptr) { //3306是mysql占用的端口,其实创建40个连接 pool = new ConnectionPool("root", "********", "tcp://127.0.0.1:3306", 40); } return pool;}//得到一个连接std::shared_ptr<Connection>ConnectionPool::getConnect(){ std::lock_guard<std::mutex> locker(lock); std::shared_ptr<Connection> sp = conList.front(); conList.pop_front(); return sp;}//归还一个连接voidConnectionPool::retConnect(std::shared_ptr<Connection> &ret){ std::lock_guard<std::mutex>locker(lock); conList.push_back(ret);}
try.cpp
#include <stdio.h>#include <stdlib.h>#include <assert.h>#include <mysql_connect.h>#include <unistd.h>ConnectionPool *pool = ConnectionPool::getInstance();int main(int argc, char *argv[]){ std::shared_ptr<Connection>con; Statement *state; ResultSet *result; //获得一个连接 con = pool->getConnect(); //获得一个数据库连接对象 state = con->createStatement(); //使用XL_db这个数据库 state->execute("use XL_db"); //查询语句 result = state->executeQuery("select * from UserInfo;"); while(result->next()) { int id = result->getInt("uid"); std::string name = result->getString("password"); std::cout << "id:" << id << " name:" << name << std::endl; } sleep(10); pool->retConnect(con); std::cout << pool->getPoolSize() << std::endl; sleep(10); return EXIT_SUCCESS;}
我自己进行了测试,创建数据库连接池,调用一个对象,然后执行数据库连接,查询出了结果,然后归还一个连接。
创建连接池前
创建连接池后
Id 792是我调用的那个连接,然后执行查询操作,所以db显示的是连接上XL_db。
这个是自己写的一个简单的数据库连接池,可以参考下,如果要使用的话还需要自己改改。
这些××池之类,比如线程池,进程池,连接池等原理都差不多,就是先创建一批对象,然后一个队列里保存,需要的时候来取,用完归还就行,然后通过c++11新特性等我们能提升性能和安全性以及程序的简介性,比如刚才说的std::move和智能指针,lambda等。
1 0
- C实现PHP的mysql数据库连接池
- 纯c语言实现数据库连接
- 基于Mysql Connector(C++)的数据库连接池的实现
- 基于Mysql Connector(C++)的数据库连接池的实现
- 基于Mysql Connector(C++)的数据库连接池的实现
- 基于Mysql Connector(C++)的数据库连接池的实现
- Mysql Connector(C++)的数据库连接池的实现
- java实现数据库连接池
- 数据库连接池实现原理
- 自己实现数据库连接池
- Java数据库连接池实现
- 自己实现数据库连接池
- 数据库连接池-DataSource实现
- JAVA数据库连接池实现
- 数据库连接池实现
- 数据库连接池实现原理
- Java 数据库连接池 实现
- JAVA数据库连接池实现
- 如何用jquery写一个简单的返回顶部
- eclipse中SVN分支合并到主干
- String,StringBuffer,StringBuilder比较
- oc010---protocol
- 给出a的定义 -- 指针 和 数组
- c++ 实现数据库连接池
- 操作系统 进程调度算法 浅析
- 关于中文乱码
- 关系型数据库与NOSQL基本概念
- ioremap 函数映射操作已知的物理地址(寄存器、端口、IO)
- 小白学开发(iOS)OC_类和对象(2015-07-22)
- 一句话说明浮点数为何不能直接 if(f== 0.0)这样判断
- Linux kernel 分析之二十:内存管理-内核中的页表映射总结
- UVA11997 K Smallest Sums(并归,优先队列)