当前位置:Gxlcms > 数据库问题 > c++ 实现数据库连接池

c++ 实现数据库连接池

时间:2021-07-01 10:21:17 帮助过:30人阅读

#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();
}

//得到连接池大小
int
ConnectionPool::getPoolSize()
{
    return conList.size();
}

//增加连接
void
ConnectionPool::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));
    }
}

//初始化连接池
void
ConnectionPool::initConnectPool(int initialSize)
{
    //加锁,增添一个连接
    std::lock_guard<std::mutex> locker(lock);
    addConn(initialSize);
}

//销毁一个连接
void
ConnectionPool::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();
    }
}

//扩大连接池
void
ConnectionPool::expandPool(int size)
{
    std::lock_guard<std::mutex> locker(lock);
    addConn(size);
    poolSize += size;
}

//缩小连接池
void
ConnectionPool::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;
}

//归还一个连接
void
ConnectionPool::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等。

版权声明:本文为博主原创文章,未经博主允许不得转载。

c++ 实现数据库连接池

标签:数据库连接   删除   c++   delete   代码   

人气教程排行