基于C++实现Mysql数据库连接池实例

 更新时间:2022年12月07日 09:28:09   作者:小杰312  
数据库连接池负责分配、管理、和释放数据库连接,允许使用应用程序重复使用一个现有的数据库连接。数据库连接是关键有限且昂贵的资源,一个数据库连接对象均对应一个物理数据库的连接,每次操作都打开一个物理连接,使用完都关闭连接

项目技术点

  • C语言进行MYSQL数据库编程
  • 无锁单例
  • 基于STL队列加C++11新特性保证线程安全实现的生产者消费者模型
  • C++11多线程编程 (线程间同步与互斥)
  • 基于CAS的原子整形
  • lambda表达式
  • shared_ptr智能指针管理Connection*指针对象
  • 基于C++11标准库实现, 具备跨平台的特性,省去了对于pthread库的C++的封装.更加针对于项目的核心逻辑上的思考和实现. (主干到细节)
  • Makefile自动化编译

项目意义

高并发场景下, 频繁创建, 销毁连接带来的性能损耗

三次握手,连接认证(身份权限认证),MySQL资源释放, 四次挥手

每一次client 访问 Mysql server都需要进行上述操作. 上述这些操作是固定的流程. 真正的sql语句执行操作才是我们无法逃脱的, 所以上述这些我们完全可以提前创建出来,然后进行不断的复用connections. 实现mysql server访问的性能提升.

思考: 提前创建好的 connetions 数目是否是越多越好?

当然是不可能,因为每一个connection都是需要占据一定的系统资源的, 创建过多的connection 会导致服务器资源紧张. 起码per connection per socketfd (套接字资源)

思考: connections 数目设计?

上下限限制数目. initSize控制下限. maxSize控制连接上限 (一般是系统的最大mysql connetions num)

多余connection最长闲置时间限制: maxIdleTime (及时释放闲置连接)

资源紧张, 并发访问量高. 没有连接可用 :connectionTimeout (return error, 获取连接超时时间)

项目实现

Connection设计

数据成员

MYSQL* _conn;         //连接句柄                                  
clock_t _startTime;   //连接起始空闲时间

操作接口

Connection();            //构造 init Connection
~Connection();           //析构 destroy connection
bool connect(ip, port, username, password, dbname);     //连接操作, 返回连接结果
bool update(sql);        //表更新操作, 返回更新结果 
MYSQL_RES* query(sql);   //查询操作, 返回查询结果
void refreshStartTime(); //刷新连接起始空闲时间
clock_t getAliveTime();  //获取连接空闲时间

ConnectionPool设计

数据成员

//连接登录信息
string _ip;
unsigned short _port;
string _username;
string _password;
string _dbname;
//连接数量等配置信息
int _initSize;
int _maxSize;
int _maxIdleTime;
int _connectionTimeout;
//连接存储信息,以及保证线程安全
queue<Connection*> _connectionQue;
mutex _queueLock;
condition_variable _cond;
atomic_int _connectionCnt;

操作接口

ConnectionPool();                          //构造 init pool, 加载配置, 初始连接, 启动线程
static ConnectionPool* getConnectionPool();//获取单例
shared_ptr<Connection> getConnection();    //获取连接
int _loadConfigFile(string& filename);     //加载解析配置信息
void produceConnectionTask();              //生产连接任务
void scannerConnetionTask();               //扫描监视销毁空闲线程任务

项目复杂接口细节刨析

getConnection()

/*
    从连接池中获取一条连接. 相当于是消费者
    消费前提, _connectionQue中有货, 所以无货期间需要进行阻塞休眠等待. 
    等待也不能一直等待. 存在连接超时时间, 
    waittime >= _connectionTimeout then output << error.
*/
shared_ptr<Connection> getConnection() {
    unique_lock<mutex> auto_lock(_queueLock);//定义智能锁
    while (_connectionQue.empty()) {
        if (cv_status::timeout == _cond.wait_for(auto_lock,                                          chrono::milliseconds(_connectionTimeout))) { //达到连接超时时间
            if (_connectionQue.empty()) {
                //LOG DEBUG INFO
                cerr << "获取连接超时" << endl;
                return nullptr;
            }
        }
    }
    //定义shared_ptr<Connection> 自定义del函数, 而非直接调用~T()
    shared_ptr<Connection> sp(_connectionQue.front(), [&](Connection* pconn){
        unique_lock<mutex> auto_lock(_queueLock);
        pconn->refreshStartTime();      //刷新连接起始空闲时间
        _connectionQue.push(pconn);
    });
    _connectionQue.pop();
    _cond.notify_all();                 //弹出任务, queue maybe empty notify produce
    return sp;
}

produceConnectionTask()

/*
    生产者线程任务. 在_connectionQue中无connetion 
    && _connectionCnt < _maxSize 时候 及时创建连接填充_connectionQue。                   
*/
void produceConnectionTask() {
    for (;;) {
        unique_lock<mutex> auto_lock(_queueLock);
        while (!_connectionQue.empty()) {
            _cond.wait(auto_lock);
        }
        if (_connectionCnt < _maxSize) {
            Connection* pconn = new Connection();
            pconn->connet(_ip, _port, _username, _password, _dbname);
            pconn->refreshStartTime();
            _connectionQue.push(pconn);
            _connectionCnt++;
        }
        _cond.notify_all(); //通知消费
    }
}
​

scannerConnetionTask()

/*
	不停的扫描所有的connection, 从头到尾的扫描, 
    监控销毁哪些长期空闲的connection, 避免对于空闲资源的无端占用浪费.  
    每一次休眠一个 _maxIdleTime 就出来 检查, 定期轮询检查空闲丽连接进行销毁
*/
void scannerConnectionTask() {
    for (;;) {
        //休眠maxIdleTime
    	this_thread::sleep_for(chrono::seconds(_maxIdleTime));   
        unique_lock<mutex> auto_lock(_queueLock);
        while (_connectionCnt > _initSize)
		{
			Connection *p = _connectionQue.front();
			if (p->getAliveeTime()/SECONDS_PER_SEC >= _maxIdleTime)
			{
				_connectionQue.pop();
				_connectionCnt--;
				delete p; // 调用~Connection()释放连接
			}
			else
			{
				break; // 队头的连接没有超过_maxIdleTime,其它连接肯定没有
			}
		}       
    }
}

到此这篇关于基于C++实现Mysql数据库连接池实例的文章就介绍到这了,更多相关C++数据库连接池内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 教你如何在Mac上安装mysql数据库

    教你如何在Mac上安装mysql数据库

    本文给大家详细介绍了如何在Mac上安装mysql数据库的方法,非常的细致,有需要的小伙伴可以参考下
    2018-05-05
  • MySQL5.7.21解压版安装详细教程图解

    MySQL5.7.21解压版安装详细教程图解

    对于小编来说安装系统软件是常干的事情,今天小编抽空给大家整理了MySQL5.7.21解压版安装详细教程图解,非常不错,具有一定的参考借鉴价值,需要的朋友参考下吧
    2018-09-09
  • MySQL中TEXT类型存储极限与实践案例

    MySQL中TEXT类型存储极限与实践案例

    本文解析MySQL TEXT类型存储极限及工程实践,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2022-10-10
  • 浅谈MySQL 中 null 值的那些坑

    浅谈MySQL 中 null 值的那些坑

    本文解析MySQL中null值的定义与常见问题,如比较运算符失效、WHERE条件误用、IN子查询异常,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-09-09
  • MySQL数据库子查询语法规则详解

    MySQL数据库子查询语法规则详解

    子查询是在查询语句里面再嵌套一个查询,这是因为我们在提取数据的时候有很多不知道的数据产生了依赖关系。本文为大家总结了一下MySQL数据库子查询语法规则,感兴趣的可以了解一下
    2022-08-08
  • Mysql中left join、right join和inner join(join)的区别及说明

    Mysql中left join、right join和inner join(join)的区

    本文介绍了leftjoin、rightjoin和innerjoin的区别和使用场景,以图文形式辅以实例讲解,帮助读者清晰理解三种SQL连接查询的特点和应用
    2024-10-10
  • mysql查询连续记录方式

    mysql查询连续记录方式

    这篇文章主要介绍了mysql查询连续记录方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-05-05
  • mysql死锁和分库分表问题详解

    mysql死锁和分库分表问题详解

    这篇文章主要给大家介绍了关于mysql死锁和分库分表问题的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-04-04
  • Mysql 忘记root密码和修改root密码的解决方法(小结)

    Mysql 忘记root密码和修改root密码的解决方法(小结)

    这篇文章主要介绍了Mysql 忘记root密码和修改root密码的解决方法(小结),非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2016-12-12
  • mysql_fetch_row()与mysql_fetch_array()的使用介绍

    mysql_fetch_row()与mysql_fetch_array()的使用介绍

    本篇文章是对mysql_fetch_row()与mysql_fetch_array()的使用进行了详细的分析介绍,需要的朋友参考下
    2013-06-06

最新评论