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

如何利用C++實(shí)現(xiàn)mysql數(shù)據(jù)庫(kù)的連接池詳解

 更新時(shí)間:2021年07月31日 09:11:14   作者:一只會(huì)鏟史的貓  
為了提高M(jìn)ySQL數(shù)據(jù)庫(kù)的訪問(wèn)的瓶頸,除了在服務(wù)器端增設(shè)緩存服務(wù)器緩存常用的數(shù)據(jù)之外(如redis),還可以增加數(shù)據(jù)庫(kù)連接池,來(lái)提高M(jìn)ySQL Server的訪問(wèn)效率,這篇文章主要給大家介紹了關(guān)于如何利用C++實(shí)現(xiàn)mysql數(shù)據(jù)庫(kù)的連接池的相關(guān)資料,需要的朋友可以參考下

為什么是mysql?

現(xiàn)在幾乎所有的后臺(tái)應(yīng)用都要用到數(shù)據(jù)庫(kù),什么關(guān)系型的、非關(guān)系型的;正當(dāng)關(guān)系的,不正當(dāng)關(guān)系的;主流的和非主流的, 大到Oracle,小到sqlite,以及包括現(xiàn)在逐漸流行的基于物聯(lián)網(wǎng)的時(shí)序數(shù)據(jù)庫(kù),比如濤思的TDengine,咱們中國(guó)人自己的開(kāi)源時(shí)序數(shù)據(jù)庫(kù),性能杠杠滴。

凡此總總,即使沒(méi)用過(guò),也聽(tīng)說(shuō)過(guò),但大部分人或企業(yè)用的最多的就是白嫖型數(shù)據(jù)庫(kù):mysql。該數(shù)據(jù)庫(kù)的特點(diǎn)就是無(wú)論是個(gè)人還是企業(yè)都能玩的起。像Oracle這種名媛型數(shù)據(jù)庫(kù)基本就屬于銀行特供,銀行需要花錢(qián)買(mǎi)平安,心里踏實(shí)。不買(mǎi)對(duì)的,只選貴的,因?yàn)槿思掖_實(shí)不差錢(qián)。

如果你的后臺(tái)應(yīng)用連數(shù)據(jù)庫(kù)都不需要,那跟咸魚(yú)網(wǎng)站有什么區(qū)別呢?就是咸魚(yú)二手網(wǎng)也要用到數(shù)據(jù)庫(kù)的。如果一個(gè)IT民工一輩子沒(méi)用過(guò)數(shù)據(jù)庫(kù)就在35(~45)歲時(shí)“被退休”,那他的職業(yè)生涯是遺憾的,是不完美的,是不純粹的。 好歹年輕是也要用一下非主流的Access吧,哪怕Execel也成。這種感覺(jué)就好比在大學(xué)時(shí)沒(méi)談過(guò)戀愛(ài)一樣,光忙著羨慕別人就突然畢業(yè)了。

為什么要搞資源池?

目前大部分后臺(tái)程序都選擇Java開(kāi)發(fā)或PHP,這兩種語(yǔ)言的第三方庫(kù)非常豐富,豐富到讓開(kāi)發(fā)人員的只要將精力放在具體業(yè)務(wù)上即可。比如數(shù)據(jù)庫(kù)的資源池,只要選擇好適當(dāng)?shù)膉ar包外加配置好相應(yīng)的數(shù)據(jù)庫(kù)參數(shù),即可放心大膽的使用mysql。

當(dāng)然,如果你命硬的話(huà),也可以選擇用C或C++開(kāi)發(fā)后臺(tái)應(yīng)用。這時(shí)候你就需要自己DIY一個(gè)數(shù)據(jù)庫(kù)資源池。

如果只是一個(gè)客戶(hù)端程序,基本不需要連接池,但對(duì)于后臺(tái)應(yīng)用來(lái)說(shuō),高并發(fā)就意味著多線(xiàn)程,多線(xiàn)程程就意味著資源的競(jìng)爭(zhēng)。內(nèi)存訪問(wèn)如此,數(shù)據(jù)庫(kù)訪問(wèn)也是如此。每次數(shù)據(jù)庫(kù)的打開(kāi)和關(guān)閉就是一次網(wǎng)絡(luò)連接和關(guān)閉的過(guò)程,頻繁的打開(kāi)和關(guān)閉無(wú)疑會(huì)浪費(fèi)大量的系統(tǒng)資源。這時(shí)候就需要提前建立好N個(gè)連接,并放在資源池中并提供給不同線(xiàn)程訪問(wèn)使用。

mysql資源池實(shí)現(xiàn)的案例源碼

我一直相信好的代碼是不需要過(guò)的語(yǔ)言來(lái)解釋的,代碼即文檔,要啥自行車(chē)。以下案例只是一個(gè)實(shí)現(xiàn)思路,供參考。

頭文件:MysqlPool.h

#pragma warning(disable : 4786) 

#include <windows.h>
#include <winsock2.h>
#include <mysql.h>     // 確保你的機(jī)器有mysql開(kāi)發(fā)庫(kù)
#include <vector>
#include <string>
using namespace std;

#define DEFAULT_POOL_SIZE  20 // 缺省mysql連接池中的數(shù)量
#define DEFAULT_POOL_TIMEOUT 60 // 獲取池中mysql連接的超時(shí)

// 自定義數(shù)據(jù)庫(kù)查詢(xún)回調(diào)函數(shù)
typedef BOOL (CALLBACK *LPFN_RetrieveRecordData)(MYSQL_ROW& sqlRow, MYSQL_FIELD* pSqlFields, int iFieldCount, DWORD dwUserData);

// Mysql數(shù)據(jù)庫(kù)連接類(lèi)
class CMysqlConn
{
public:
 CMysqlConn(const char* pszDBServer, UINT uDBPort, const char* pszDBName, 
    const char* pszDBUser, const char* pszDBPwd);
 virtual ~CMysqlConn();
 
public:
 // 打開(kāi)/關(guān)閉一個(gè)mysql連接
 BOOL Open();
 void Close();
 
 // ping連接是否已關(guān)閉
 BOOL Ping();
 // 重置字符集
 BOOL ResetCharset();
 
 
public:
 // ================SQL語(yǔ)句操作(簡(jiǎn)單實(shí)現(xiàn)幾個(gè))================
 // 查詢(xún)
 BOOL Select(const char* pszSql, LPFN_RetrieveRecordData lpfnRetrieveRecordData, DWORD dwUserData);
 // 執(zhí)行
 BOOL Execute(const char* pszSql);
 // 插入,如果主鍵是自增整型,返回插入后的主鍵值
 __int64 Insert(const char* pszSql);
 
 
protected:
 MYSQL* m_pMysql;   // mysql數(shù)據(jù)庫(kù)操作對(duì)象

 // 以下是連接mysql需要的參數(shù)
 string m_strDBServer;  // mysql數(shù)據(jù)庫(kù)所在服務(wù)器
 UINT m_uDBPort;   // mysql數(shù)據(jù)庫(kù)連接端口
 string m_strDBName;  // 數(shù)據(jù)庫(kù)名稱(chēng)
 string m_strDBUser;  // 數(shù)據(jù)庫(kù)賬戶(hù)
 string m_strDBPwd;   // 數(shù)據(jù)庫(kù)密碼
 
};

// 數(shù)據(jù)庫(kù)連接池實(shí)現(xiàn)
class CMysqlPool  
{
public:
 CMysqlPool();
 virtual ~CMysqlPool();

 // 創(chuàng)建mysql連接池
 BOOL Create(const char* pszDBServer, UINT uDBPort, const char* pszDBName, 
    const char* pszDBUser, const char* pszDBPwd,
     DWORD dwPoolSize = DEFAULT_POOL_SIZE, 
    DWORD dwTimeOut = DEFAULT_POOL_TIMEOUT);   
 // 銷(xiāo)毀連接池
  void Destroy();
  
public:

 // 獲取一個(gè)mysql連接
  CMysqlConn* Get();

 // 釋放一個(gè)mysql連接
  void Release(CMysqlConn* pConn);
 
protected:
 HANDLE    m_hSemaphore;       // 信號(hào)量句柄
 DWORD    m_dwPoolSize;  // 連接池大小 
 DWORD    m_dwTimeOut;  // 超時(shí),單位秒
 CRITICAL_SECTION m_csPool;   // 連接池鎖

 vector<CMysqlConn*> m_vecIdle;   // 閑隊(duì)列
 vector<CMysqlConn*> m_vecBusy;   // 忙隊(duì)列
};

實(shí)現(xiàn)文件:MysqlPool.cpp

#include "stdafx.h"
#include "MysqlPool.h"
#include <assert.h>
#include <algorithm>

#pragma comment(lib, "libmysql.lib") //連接MysQL需要的庫(kù)

//////////////////////////////////////////////////////////////////////
// CMysqlConn: mysql數(shù)據(jù)庫(kù)連接類(lèi)
//////////////////////////////////////////////////////////////////////

CMysqlConn::CMysqlConn(const char* pszDBServer, UINT uDBPort, const char* pszDBName, 
      const char* pszDBUser, const char* pszDBPwd)
{
 assert(pszDBServer);
 assert(pszDBName);
 assert(pszDBUser);
 assert(pszDBPwd);

 m_pMysql = NULL;
 m_strDBServer = pszDBServer;
 m_uDBPort = uDBPort;
 m_strDBName = pszDBName;
 m_strDBUser = pszDBUser;
 m_strDBPwd = pszDBPwd;
}

CMysqlConn::~CMysqlConn()
{
 Close();
}

// 打開(kāi)一個(gè)mysql數(shù)據(jù)庫(kù),即建立一個(gè)數(shù)據(jù)庫(kù)連接
BOOL CMysqlConn::Open()
{
 if(m_pMysql)
 {
  mysql_close(m_pMysql); // 關(guān)閉連接 
  m_pMysql = NULL;
 }
 
 m_pMysql = mysql_init(NULL);
 if(!m_pMysql)
  return FALSE;
 
 // 連接數(shù)據(jù)庫(kù)
    if(!mysql_real_connect(m_pMysql, m_strDBServer.c_str(), m_strDBUser.c_str(),
       m_strDBPwd.c_str(), m_strDBName.c_str(), m_uDBPort, NULL, 0))
    {
  int i = mysql_errno(m_pMysql);
  const char * pszErr = mysql_error(m_pMysql);

  return FALSE;
 }
 
 // 設(shè)置重連
 char chValue = 1;
 mysql_options(m_pMysql, MYSQL_OPT_RECONNECT, &chValue); 
 mysql_query(m_pMysql,"set names 'gbk'"); 
 
 return TRUE;
}

// 關(guān)閉數(shù)據(jù)庫(kù)連接
void CMysqlConn::Close()
{
 if(m_pMysql)
  mysql_close(m_pMysql); // 斷開(kāi)連接
 m_pMysql = NULL; 
}

// ping一下mysql,看看連接還活著
BOOL CMysqlConn::Ping()
{
 if(m_pMysql)
  return (0 == mysql_ping(m_pMysql));
 return FALSE;
}

// 設(shè)置字符集為GBK
BOOL CMysqlConn::ResetCharset()
{
 if(m_pMysql)
  return (0 == mysql_query(m_pMysql, "set names 'gbk'")); 
 return FALSE;
}

// mysql執(zhí)行:delete 或 update
BOOL CMysqlConn::Execute(const char* pszSql)
{
 assert(pszSql);

 if(!m_pMysql)
  return FALSE;
 
 MYSQL_STMT *myStmt = mysql_stmt_init(m_pMysql);
 if(!myStmt)
 {
  return FALSE;
 }
 
 if(0 != mysql_stmt_prepare(myStmt, pszSql, strlen(pszSql)))
 {
  mysql_stmt_close(myStmt);
  return FALSE;
 }
 if(0 != mysql_stmt_execute(myStmt))
 {
  mysql_stmt_close(myStmt);
  return FALSE;
 }
 mysql_stmt_close(myStmt);
 
 return TRUE;  
}

// mysql插入
__int64 CMysqlConn::Insert(const char* pszSql)
{ 
 assert(pszSql);

 MYSQL_STMT *myStmt = mysql_stmt_init(m_pMysql);
 if(!myStmt)
  return 0;
 
 if(0 != mysql_stmt_prepare(myStmt, pszSql, strlen(pszSql)))
 {
  int i = mysql_errno(m_pMysql);
  const char * s = mysql_error(m_pMysql);
  mysql_stmt_close(myStmt);
  return 0;
 }
 if(0 != mysql_stmt_execute(myStmt))
 {
  mysql_stmt_close(myStmt);
  return 0;
 }
 mysql_stmt_close(myStmt);
 
 __int64 i64ID = mysql_insert_id(m_pMysql); 
 return i64ID;
}

// mysql查詢(xún)
BOOL CMysqlConn::Select(const char* pszSql, LPFN_RetrieveRecordData lpfnRetrieveRecordData, DWORD dwUserData)
{
 if(!m_pMysql)
  return FALSE;
 
 if(NULL == lpfnRetrieveRecordData)
  return FALSE;
 
 if(0 != mysql_real_query(m_pMysql, pszSql, strlen(pszSql)))
 {
  return FALSE; 
 }
 
 MYSQL_RES *resRecord = mysql_store_result(m_pMysql);
 int iFieldCount = resRecord->field_count;
 
 MYSQL_ROW sqlRow;
 while (sqlRow = mysql_fetch_row(resRecord))
    {
  if(!lpfnRetrieveRecordData(sqlRow, resRecord->fields, iFieldCount, dwUserData))
   break;
 }
 mysql_free_result(resRecord);
 return TRUE;
}

//////////////////////////////////////////////////////////////////////
// CMysqlPool: mysql數(shù)據(jù)庫(kù)連接池類(lèi)
//////////////////////////////////////////////////////////////////////

CMysqlPool::CMysqlPool()
{
 ::InitializeCriticalSection(&m_csPool);
}

CMysqlPool::~CMysqlPool()
{
 Destroy();
 ::DeleteCriticalSection(&m_csPool);
}

// 創(chuàng)建mysql連接池
BOOL CMysqlPool::Create(const char* pszDBServer, UINT uDBPort, const char* pszDBName, 
      const char* pszDBUser, const char* pszDBPwd,
      DWORD dwPoolSize, DWORD dwTimeOut)
{
 m_dwTimeOut = dwTimeOut;
 m_dwPoolSize = dwPoolSize;
 
 // 創(chuàng)建信號(hào)量
 m_hSemaphore = ::CreateSemaphore(NULL, dwPoolSize, dwPoolSize, NULL);
 if (NULL == m_hSemaphore)
 {
  return FALSE;
 }
 
 // 創(chuàng)建數(shù)據(jù)庫(kù)連接池
 for(DWORD i = 0; i < dwPoolSize; ++i)
 {
  // 創(chuàng)建一個(gè)mysql數(shù)據(jù)庫(kù)連接
  CMysqlConn *pConn = new CMysqlConn(pszDBServer, uDBPort, pszDBName, pszDBUser, pszDBPwd);
  if(!pConn->Open()) 
  {
   delete pConn;
   continue;
  }
  m_vecIdle.push_back(pConn);
 }

 return m_vecIdle.size() > 0;
 
}

// 銷(xiāo)毀mysql連接池
void CMysqlPool::Destroy()
{
 ::CloseHandle(m_hSemaphore);
 m_hSemaphore = NULL;
 
 // 釋放idle隊(duì)列
 vector<CMysqlConn*>::iterator it;
    for(it = m_vecIdle.begin(); it != m_vecIdle.end(); ++it)
 {
  CMysqlConn* pConn =  *it;
  delete pConn;
 }
 m_vecIdle.clear();
 
 // 釋放busy隊(duì)列
 while(!m_vecBusy.empty())
 {
  CMysqlConn* pConn =  m_vecBusy.back();
  m_vecBusy.pop_back();
  delete pConn;
 } 
}

// 從mysql連接池獲取一個(gè)連接
CMysqlConn* CMysqlPool::Get()
{
 DWORD dwRet = ::WaitForSingleObject(m_hSemaphore, m_dwTimeOut*1000);
 
 if (WAIT_OBJECT_0 != dwRet)    // 超時(shí),說(shuō)明資源池沒(méi)有可用mysql連接
 {
  printf("數(shù)據(jù)庫(kù)沒(méi)有可用連接。\r\n");
  return NULL;
 }
 
 // 從連接池中獲取一個(gè)閑置連接
 CMysqlConn* pConn = NULL;

 ::EnterCriticalSection(&m_csPool);

  if (!m_vecIdle.empty())
  {
  pConn = m_vecIdle.back();   // 移出idle隊(duì)列
   m_vecIdle.pop_back(); 
   m_vecBusy.push_back(pConn);   // 加入busy隊(duì)列
  }
 ::LeaveCriticalSection(&m_csPool);
 
 if(NULL == pConn)
  return NULL;
 
 // 如果一個(gè)連接長(zhǎng)時(shí)間無(wú)通信,可能被防火墻關(guān)閉,此時(shí)可以通過(guò)mysql_ping函數(shù)測(cè)試一下
 // 本例中通過(guò)重新設(shè)置字符集
 // 重新設(shè)置字符集,并判斷數(shù)據(jù)庫(kù)連接是否已斷開(kāi)
 if(!pConn->ResetCharset())   
 {
  if(!pConn->Open())
   return NULL;
 }
 
 printf("==》資源池:記得還我哦。\r\n");
 return pConn;
}

// 釋放一個(gè)連接到mysql連接池
void CMysqlPool::Release(CMysqlConn* pConn)
{
 if(NULL == pConn)
  return;
 
 // 釋放一個(gè)信號(hào)量
 ::ReleaseSemaphore(m_hSemaphore, 1, NULL); 

 ::EnterCriticalSection(&m_csPool);

 // 從Busy隊(duì)列中釋放該連接
 vector<CMysqlConn*>::iterator it = find(m_vecBusy.begin(), m_vecBusy.end(), pConn);
 if(it != m_vecBusy.end())
 {
  printf("POOL SIZE : %d, %d\r\n", m_vecIdle.size(), m_vecBusy.size());
  m_vecBusy.erase(it);    // 移出busy隊(duì)列
  m_vecIdle.push_back(pConn);   // 加入idle隊(duì)列
  printf("POOL SIZE : %d, %d\r\n", m_vecIdle.size(), m_vecBusy.size());
 }
 ::LeaveCriticalSection(&m_csPool);
 
 printf("《==資源池說(shuō):有借有還再借不難,常來(lái)玩啊。\r\n");
}

測(cè)試函數(shù)

void TestMysqlPool()
{
 // 創(chuàng)建mysql連接資源池
 CMysqlPool mysqlPool;
 if(!mysqlPool.Create("127.0.0.1", 3306, "information_schema", "root", "123456"))
 {
  printf("Create mysql conneticon pool failed.\r\n");
  return;
 }

 // 從資源池中獲取一個(gè)連接,連接池說(shuō):記得要還哦!
 CMysqlConn* pConn = mysqlPool.Get();

 // 假裝做一次數(shù)據(jù)庫(kù)操作
 char* pszSQL =  "SELECT * FROM CHARACTER_SETS";
 pConn->Select(pszSQL, RetrieveRecordData, 0);

 // 將連接還給資源池并謝謝!連接池說(shuō):不客氣!
 mysqlPool.Release(pConn);

 printf("Test over.\r\n");
}

輸出打印

總結(jié)

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

相關(guān)文章

  • C語(yǔ)言實(shí)題講解快速掌握單鏈表上

    C語(yǔ)言實(shí)題講解快速掌握單鏈表上

    單鏈表是后面要學(xué)的雙鏈表以及循環(huán)鏈表的基礎(chǔ),要想繼續(xù)深入了解數(shù)據(jù)結(jié)構(gòu)以及C語(yǔ)言,我們就要奠定好這塊基石!接下來(lái)就和我一起學(xué)習(xí)吧
    2022-04-04
  • C語(yǔ)言 深入解讀數(shù)據(jù)結(jié)構(gòu)之堆的實(shí)現(xiàn)

    C語(yǔ)言 深入解讀數(shù)據(jù)結(jié)構(gòu)之堆的實(shí)現(xiàn)

    堆就是用數(shù)組實(shí)現(xiàn)的二叉樹(shù),所以它沒(méi)有使用父指針或者子指針。堆根據(jù)“堆屬性”來(lái)排序,“堆屬性”決定了樹(shù)中節(jié)點(diǎn)的位置
    2021-11-11
  • C語(yǔ)言深入探索遞歸的特點(diǎn)

    C語(yǔ)言深入探索遞歸的特點(diǎn)

    程序調(diào)???的編程技巧稱(chēng)為遞歸 recursion)函數(shù)??調(diào)???就是遞歸,你也可以理解成是?種嵌套結(jié)構(gòu),但遞歸分為倆部分,第?是“遞”,進(jìn)?嵌套結(jié)構(gòu)。第?是”歸“,最終會(huì)?步?步返回。第?次接觸遞歸都會(huì)很懵,慢慢理解這個(gè)過(guò)程就明?了
    2022-06-06
  • 2048小游戲C語(yǔ)言實(shí)現(xiàn)代碼

    2048小游戲C語(yǔ)言實(shí)現(xiàn)代碼

    這篇文章主要為大家詳細(xì)介紹了2048小游戲C語(yǔ)言實(shí)現(xiàn)代碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-05-05
  • 詳解C語(yǔ)言中的動(dòng)態(tài)內(nèi)存管理

    詳解C語(yǔ)言中的動(dòng)態(tài)內(nèi)存管理

    對(duì)于數(shù)據(jù)的存儲(chǔ)我們可以靜態(tài)存儲(chǔ),也可以動(dòng)態(tài)存儲(chǔ),兩種方式都有自己特有的好處,這篇文章教我們?nèi)绾瓦M(jìn)行動(dòng)態(tài)的數(shù)據(jù)存儲(chǔ)?。。?!感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2022-12-12
  • C++二叉樹(shù)實(shí)現(xiàn)詞頻分析功能

    C++二叉樹(shù)實(shí)現(xiàn)詞頻分析功能

    這篇文章主要為大家詳細(xì)介紹了C++二叉樹(shù)實(shí)現(xiàn)詞頻分析功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-12-12
  • C++實(shí)現(xiàn)大數(shù)相乘算法

    C++實(shí)現(xiàn)大數(shù)相乘算法

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)大數(shù)相乘算法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-09-09
  • C++中的Z字形變換問(wèn)題

    C++中的Z字形變換問(wèn)題

    將一個(gè)給定字符串?s?根據(jù)給定的行數(shù)?numRows?,以從上往下、從左到右進(jìn)行?Z?字形排列,這樣一個(gè)需求怎么實(shí)現(xiàn)呢,下面小編給大家?guī)?lái)了C++中的Z字形變換問(wèn)題,需要的朋友可以參考下
    2022-07-07
  • 使用設(shè)計(jì)模式中的單例模式來(lái)實(shí)現(xiàn)C++的boost庫(kù)

    使用設(shè)計(jì)模式中的單例模式來(lái)實(shí)現(xiàn)C++的boost庫(kù)

    這篇文章主要介紹了使用設(shè)計(jì)模式中的單例模式來(lái)實(shí)現(xiàn)C++的boost庫(kù)的方法,其中作者對(duì)線(xiàn)程安全格外強(qiáng)調(diào),需要的朋友可以參考下
    2016-03-03
  • C語(yǔ)言詳解實(shí)現(xiàn)字符菱形的方法

    C語(yǔ)言詳解實(shí)現(xiàn)字符菱形的方法

    字符菱形是指給定一個(gè)字符,用它構(gòu)造一個(gè)對(duì)角線(xiàn)長(zhǎng)5個(gè)字符,傾斜放置的菱形。輸入輸入只有一行, 包含一個(gè)字符。輸出該字符構(gòu)成的菱形
    2022-04-04

最新評(píng)論