欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

基于C++實(shí)現(xiàn)Mysql數(shù)據(jù)庫連接池實(shí)例

 更新時(shí)間:2022年12月07日 09:28:09   作者:小杰312  
數(shù)據(jù)庫連接池負(fù)責(zé)分配、管理、和釋放數(shù)據(jù)庫連接,允許使用應(yīng)用程序重復(fù)使用一個(gè)現(xiàn)有的數(shù)據(jù)庫連接。數(shù)據(jù)庫連接是關(guān)鍵有限且昂貴的資源,一個(gè)數(shù)據(jù)庫連接對(duì)象均對(duì)應(yīng)一個(gè)物理數(shù)據(jù)庫的連接,每次操作都打開一個(gè)物理連接,使用完都關(guān)閉連接

項(xiàng)目技術(shù)點(diǎn)

  • C語言進(jìn)行MYSQL數(shù)據(jù)庫編程
  • 無鎖單例
  • 基于STL隊(duì)列加C++11新特性保證線程安全實(shí)現(xiàn)的生產(chǎn)者消費(fèi)者模型
  • C++11多線程編程 (線程間同步與互斥)
  • 基于CAS的原子整形
  • lambda表達(dá)式
  • shared_ptr智能指針管理Connection*指針對(duì)象
  • 基于C++11標(biāo)準(zhǔn)庫實(shí)現(xiàn), 具備跨平臺(tái)的特性,省去了對(duì)于pthread庫的C++的封裝.更加針對(duì)于項(xiàng)目的核心邏輯上的思考和實(shí)現(xiàn). (主干到細(xì)節(jié))
  • Makefile自動(dòng)化編譯

項(xiàng)目意義

高并發(fā)場(chǎng)景下, 頻繁創(chuàng)建, 銷毀連接帶來的性能損耗

三次握手,連接認(rèn)證(身份權(quán)限認(rèn)證),MySQL資源釋放, 四次揮手

每一次client 訪問 Mysql server都需要進(jìn)行上述操作. 上述這些操作是固定的流程. 真正的sql語句執(zhí)行操作才是我們無法逃脫的, 所以上述這些我們完全可以提前創(chuàng)建出來,然后進(jìn)行不斷的復(fù)用connections. 實(shí)現(xiàn)mysql server訪問的性能提升.

思考: 提前創(chuàng)建好的 connetions 數(shù)目是否是越多越好?

當(dāng)然是不可能,因?yàn)槊恳粋€(gè)connection都是需要占據(jù)一定的系統(tǒng)資源的, 創(chuàng)建過多的connection 會(huì)導(dǎo)致服務(wù)器資源緊張. 起碼per connection per socketfd (套接字資源)

思考: connections 數(shù)目設(shè)計(jì)?

上下限限制數(shù)目. initSize控制下限. maxSize控制連接上限 (一般是系統(tǒng)的最大mysql connetions num)

多余connection最長閑置時(shí)間限制: maxIdleTime (及時(shí)釋放閑置連接)

資源緊張, 并發(fā)訪問量高. 沒有連接可用 :connectionTimeout (return error, 獲取連接超時(shí)時(shí)間)

項(xiàng)目實(shí)現(xiàn)

Connection設(shè)計(jì)

數(shù)據(jù)成員

MYSQL* _conn;         //連接句柄                                  
clock_t _startTime;   //連接起始空閑時(shí)間

操作接口

Connection();            //構(gòu)造 init Connection
~Connection();           //析構(gòu) destroy connection
bool connect(ip, port, username, password, dbname);     //連接操作, 返回連接結(jié)果
bool update(sql);        //表更新操作, 返回更新結(jié)果 
MYSQL_RES* query(sql);   //查詢操作, 返回查詢結(jié)果
void refreshStartTime(); //刷新連接起始空閑時(shí)間
clock_t getAliveTime();  //獲取連接空閑時(shí)間

ConnectionPool設(shè)計(jì)

數(shù)據(jù)成員

//連接登錄信息
string _ip;
unsigned short _port;
string _username;
string _password;
string _dbname;
//連接數(shù)量等配置信息
int _initSize;
int _maxSize;
int _maxIdleTime;
int _connectionTimeout;
//連接存儲(chǔ)信息,以及保證線程安全
queue<Connection*> _connectionQue;
mutex _queueLock;
condition_variable _cond;
atomic_int _connectionCnt;

操作接口

ConnectionPool();                          //構(gòu)造 init pool, 加載配置, 初始連接, 啟動(dòng)線程
static ConnectionPool* getConnectionPool();//獲取單例
shared_ptr<Connection> getConnection();    //獲取連接
int _loadConfigFile(string& filename);     //加載解析配置信息
void produceConnectionTask();              //生產(chǎn)連接任務(wù)
void scannerConnetionTask();               //掃描監(jiān)視銷毀空閑線程任務(wù)

項(xiàng)目復(fù)雜接口細(xì)節(jié)刨析

getConnection()

/*
    從連接池中獲取一條連接. 相當(dāng)于是消費(fèi)者
    消費(fèi)前提, _connectionQue中有貨, 所以無貨期間需要進(jìn)行阻塞休眠等待. 
    等待也不能一直等待. 存在連接超時(shí)時(shí)間, 
    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))) { //達(dá)到連接超時(shí)時(shí)間
            if (_connectionQue.empty()) {
                //LOG DEBUG INFO
                cerr << "獲取連接超時(shí)" << endl;
                return nullptr;
            }
        }
    }
    //定義shared_ptr<Connection> 自定義del函數(shù), 而非直接調(diào)用~T()
    shared_ptr<Connection> sp(_connectionQue.front(), [&](Connection* pconn){
        unique_lock<mutex> auto_lock(_queueLock);
        pconn->refreshStartTime();      //刷新連接起始空閑時(shí)間
        _connectionQue.push(pconn);
    });
    _connectionQue.pop();
    _cond.notify_all();                 //彈出任務(wù), queue maybe empty notify produce
    return sp;
}

produceConnectionTask()

/*
    生產(chǎn)者線程任務(wù). 在_connectionQue中無connetion 
    && _connectionCnt < _maxSize 時(shí)候 及時(shí)創(chuàng)建連接填充_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(); //通知消費(fèi)
    }
}
?

scannerConnetionTask()

/*
	不停的掃描所有的connection, 從頭到尾的掃描, 
    監(jiān)控銷毀哪些長期空閑的connection, 避免對(duì)于空閑資源的無端占用浪費(fèi).  
    每一次休眠一個(gè) _maxIdleTime 就出來 檢查, 定期輪詢檢查空閑麗連接進(jìn)行銷毀
*/
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; // 調(diào)用~Connection()釋放連接
			}
			else
			{
				break; // 隊(duì)頭的連接沒有超過_maxIdleTime,其它連接肯定沒有
			}
		}       
    }
}

到此這篇關(guān)于基于C++實(shí)現(xiàn)Mysql數(shù)據(jù)庫連接池實(shí)例的文章就介紹到這了,更多相關(guān)C++數(shù)據(jù)庫連接池內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論