【数据库连接池】04:连接池空闲连接回收

发布时间:2026-03-03 02:07

智能手表可连接手机接收健康数据同步 #生活技巧# #数码产品使用技巧# #智能手表健康监测#

最新推荐文章于 2025-09-30 04:37:47 发布

原创 于 2023-11-28 09:14:25 发布 · 2k 阅读

· 26

· 21 ·

CC 4.0 BY-SA版权

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

连接池空闲连接回收

OVERVIEW 连接池空闲连接回收1.需求分析2.Connection添加字段3.CommonConnectionPool中调用刷新4.CommonConnectionPool中定时扫描CommonConnectionPool.hCommonConnectionPool.cpp 1.需求分析

多余的连接如果超过指定的时间,还没有再次被使用到,就需要将连接进行回收,从而节省服务器资源,

实现方案:

在Connection类中添加_alivetime字段,用于记录连接进入空闲状态后的起始时间,每次入队或者出队时都将Connection连接对象的_alivetime字段进行刷新,启动一个定时线程,定时扫描超过maxIdleTime的空闲连接,进行多余连接的回收操作 2.Connection添加字段

#ifndef _CONNECTION_H #define _CONNECTION_H #include <ctime> #include <string.h> #include <iostream> #include <mysql/mysql.h> using namespace std; #define LOG(str)\cout << __FILE__ << ":" << __LINE__ << " " <<\__TIMESTAMP__ << ":" << str << endl; // 封装Connection对象 实现数据库增删改查 class Connection { public:// 初始化数据库连接Connection(); // 释放数据库连接资源 ~Connection(); // 连接数据库 bool connect(string ip, unsigned short port, string user, string password, string dbname); // 更新数据库操作 insert delete update bool update(string sql); // 刷新连接的起始空闲时间点 void refreshAliveTime() { _alivetime = clock(); } // 返回连接存活的时长 clock_t getAliveTime() const { return clock() - _alivetime; } private: // 表示和 MYSQL Server的一条连接 MYSQL *_conn; // 进入空闲状态后的起始时间 clock_t _alivetime; }; #endif

cpp

运行

123456789101112131415161718192021222324252627282930313233343536 3.CommonConnectionPool中调用刷新

在初始化连接池时,添加刷新Connection连接的alivetime

// 初始化连接池 ConnectionPool::ConnectionPool() {// 1.加载配置项if (!loadConfigFile()) return;// 2.创建初始数量的连接for (int i = 0; i < _initSize; ++i) {Connection *p = new Connection();p->connect(_ip, _port, _username, _password, _dbname);p->refreshAliveTime();_connectionq.push(p);_connectionCnt++;}// 3.启动一个新的线程作为连接的生产者thread connProducer(std::bind(&ConnectionPool::produceConnTask, this)); }

cpp

运行

123456789101112131415

在消费者生产Connection连接时,刷新连接的alivetime

// 生产者线程的线程函数 void ConnectionPool::produceConnTask() {for (;;) {// 队列上锁unique_lock<mutex> lock(_queueMutex);// 若队列不空 生产者线程进入等待状态 并且将锁释放 等待为空while (!_connectionq.empty()) {condv.wait(lock);}// 连接数量没有到达上限 则继续创建新的连接if (_connectionCnt < _maxSize) {Connection *p = new Connection();p->connect(_ip, _port, _username, _password, _dbname);p->refreshAliveTime();_connectionq.push(p);_connectionCnt++;}// 通知消费者线程可以消费连接了condv.notify_all();} }

cpp

运行

12345678910111213141516171819202122

在消费者使用完毕,归还数据库连接时,需要刷新连接的alivetime

// 返回连接对象 使用智能指针管理 shared_ptr<Connection> sp(_connectionq.front(), [&](Connection *pcon){ unique_lock<mutex> lock(_queueMutex); pcon->refreshAliveTime(); _connectionq.push(pcon); });

cpp

运行

123456 4.CommonConnectionPool中定时扫描

启动一个定时线程,定时扫描超过maxIdleTime的空闲连接,进行多余连接的回收操作

CommonConnectionPool.h

#ifndef _COMMONCONNECTIONPOOL_H #define _COMMONCONNECTIONPOOL_H #include <queue> #include <string> #include <mutex> #include <atomic> #include <thread> #include <memory> #include <functional> #include <condition_variable> #include "Connection.h" using namespace std; // 实现连接池功能模块 class ConnectionPool { public:// 获取连接池实例static ConnectionPool* getConnectionPool();// 获取数据库连接shared_ptr<Connection> getConnection(); private:ConnectionPool();// 加载外部配置文件bool loadConfigFile();// 生产新连接任务函数void produceConnTask();// 定时扫描空闲连接 并进行回收操作void collectConnTask(); private:// 连接池参数int _initSize;// 初始连接量int _maxSize;// 最大连接量int _maxIdleTime;// 最大空闲时间int _connectionTimeout;// 连接超时时间// 数据库信息string _ip;unsigned short _port;string _username;string _password;string _dbname;// 数据库连接存储队列queue<Connection*> _connectionq;// 存储mysql连接的队列mutex _queueMutex;// 维护连接队列的线程安全的互斥锁atomic_int _connectionCnt;// 创建连接的数量 ++操作是线程安全的condition_variable condv;// 条件变量 用于连接生产线程和连接消费线程间的通信 }; #endif

cpp

运行

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849 CommonConnectionPool.cpp

// 初始化连接池 ConnectionPool::ConnectionPool() {// 1.加载配置项if (!loadConfigFile()) return;// 2.创建初始数量的连接for (int i = 0; i < _initSize; ++i) {Connection *p = new Connection();p->connect(_ip, _port, _username, _password, _dbname);p->refreshAliveTime();_connectionq.push(p);_connectionCnt++;}// 3.启动一个新的线程作为连接的生产者thread connProducer(std::bind(&ConnectionPool::produceConnTask, this));// 设置为守护线程connProducer.detach();// 4.启动一个新的线程 定时扫描超过maxIdleTime时间的空闲连接 对空闲连接进行回收操作thread connCollector(std::bind(&ConnectionPool::collectConnTask, this));// 设置为守护线程connCollector.detach(); } // 定时扫描空闲连接 并进行回收操作 void ConnectionPool::collectConnTask() {for (;;) {// 通过调用sleep模拟定时效果this_thread::sleep_for(chrono::seconds(_maxIdleTime));// 扫描整个连接池队列 释放多余连接unique_lock<mutex> lock(_queueMutex);while (_connectionCnt > _initSize) {Connection *p = _connectionq.front();if (p->getAliveTime() < (_maxIdleTime * 1000)) break;_connectionq.pop();_connectionCnt--;delete p;//调用Connection的析构函数释放连接}} }

cpp

运行

123456789101112131415161718192021222324252627282930313233343536373839

网址:【数据库连接池】04:连接池空闲连接回收 https://www.yuejiaxmz.com/news/view/1446297

相关内容

基于C++11的数据库连接池实现
数据库 = JDBC,连接池对象
C++连接池练习
如何主动回收连接
电动车电池连接图
sparkSQL 连接读取Oracle数据库
C#的通用DbHelper类使用数据连接池
数据库连接对象Connection对象的获取及相关知识总结
pdo连接mysql数据库(简洁明了)
判断数据库连接状态

随便看看