어떻게 C++를 이용 하여 my sql 데이터 베 이 스 를 연결 하 는 지 상세 하 게 설명 합 니 다.

왜 mysql 입 니까?
현재 거의 모든 배경 응용 은 데이터 베 이 스 를 사용 하고 어떤 관계 형,비 관계 형 을 사용 해 야 합 니까?정당한 관계 의,부당 한 관계 의;주류 와 비주류,크게 는 Oracle,작 게 는 sqlite,그리고 현재 점차적으로 유행 하고 있 는 사물 인터넷 을 바탕 으로 하 는 순차 데이터 베 이 스 를 포함한다.예 를 들 어 타 오 스 의TDengine,우리 중국인 들 의 오픈 소스 순차 데이터 베이스,성능 지렛대 방울 이다.
이 모든 것 은 사용 해 본 적 이 없어 도 들 어 본 적 이 있 지만 대부분 사람들 이나 기업 에서 가장 많이 사용 하 는 것 은 바로 오입쟁이 형 데이터 베이스:my sql 이다.이 데이터 베 이 스 는 개인 이 든 기업 이 든 모두 할 수 있 는 것 이 특징 이다.Oracle 과 같은 명 원 형 데이터 베 이 스 는 기본적으로 은행 특 공 에 속 하기 때문에 은행 은 돈 을 써 서 평안 을 사 야 하고 마음 이 든든 하 다.맞 는 것 은 사지 않 고 비 싼 것 만 선택한다.왜냐하면 남 들 은 확실히 돈 이 모자 라 지 않 기 때문이다.
만약 당신 의 백 스테이지 응용 이 데이터베이스 도 필요 하지 않다 면,소금 에 절 인 생선 사이트 와 어떤 차이 가 있 습 니까?소금 에 절 인 생선 중고 망 도 데이터 베 이 스 를 사용 해 야 한다.만약 IT 노동자 가 평생 데이터 베 이 스 를 사용 하지 않 고 35(~45)세 에'퇴직 당 했다'면 그의 직업 생활 은 유감 이 고 완벽 하지 않 으 며 순수 하지 않다.어쨌든 젊 으 면 비주류 액 세 스 를 써 야 지,엑 세 셀 이라도.이런 느낌 은 마치 대학 때 연 애 를 해 본 적 이 없 는 것 처럼 남 을 부러워 하 느 라 바 빠 서 갑자기 졸업 한 것 과 같다.
왜 자원 탱크 를 만 들 려 고 합 니까?
현재 대부분의 백 엔 드 프로그램 은 자바 개발 이나 PHP 를 선택 하고 있 으 며,이 두 언어의 제3자 라 이브 러 리 는 개발 자 들 이 구체 적 인 업무 에 만 신경 을 쓰 면 될 정도 로 풍부 하 다.예 를 들 어 데이터 뱅 크 의 자원 탱크 는 적당 한 jar 가방 을 선택 하고 해당 하 는 데이터 베 이 스 를 설정 하면 안심 하고 대담 하 게 my sql 을 사용 할 수 있 습 니 다.
물론 팔자 가 세다 면 C 나 C++로 백 엔 드 애플 리 케 이 션 을 개발 할 수도 있다.이 럴 때 는 스스로 DIY 데이터베이스 자원 탱크 가 필요 하 다.
만약 에 하나의 클 라 이언 트 프로그램 이 라면 연결 탱크 가 필요 하지 않 지만 배경 응용 에 있어 높 은 병행 은 다 중 스 레 드 를 의미 하고 다 중 스 레 드 는 자원 의 경쟁 을 의미한다.메모리 접근 도 그 렇 고 데이터베이스 접근 도 마찬가지다.매번 데이터 베 이 스 를 열 고 닫 는 것 은 네트워크 연결 과 닫 는 과정 으로 빈번 한 열 고 닫 는 것 은 의심 할 여지없이 대량의 시스템 자원 을 낭비 할 것 이다.이 럴 때 는 N 개의 연결 을 미리 만들어 자원 탱크 에 넣 고 서로 다른 스 레 드 에 접근 할 수 있 도록 제공 해 야 합 니 다.
mysql 자원 탱크 구현 사례 원본
나 는 좋 은 코드 는 지나 치지 않 는 언어 로 설명 할 필요 가 없다 고 믿 어 왔 다.코드 즉 문서,어떤 자전 거 를 원 하 는 지.아래 의 사례 는 단지 실현 사고 일 뿐 이 니 참고 하 시기 바 랍 니 다.
헤더 파일:MysqlPool.h

#pragma warning(disable : 4786) 

#include <windows.h>
#include <winsock2.h>
#include <mysql.h>     //        mysql   
#include <vector>
#include <string>
using namespace std;

#define DEFAULT_POOL_SIZE  20 //   mysql       
#define DEFAULT_POOL_TIMEOUT 60 //     mysql     

//             
typedef BOOL (CALLBACK *LPFN_RetrieveRecordData)(MYSQL_ROW& sqlRow, MYSQL_FIELD* pSqlFields, int iFieldCount, DWORD dwUserData);

// Mysql      
class CMysqlConn
{
public:
 CMysqlConn(const char* pszDBServer, UINT uDBPort, const char* pszDBName, 
    const char* pszDBUser, const char* pszDBPwd);
 virtual ~CMysqlConn();
 
public:
 //   /    mysql  
 BOOL Open();
 void Close();
 
 // ping       
 BOOL Ping();
 //      
 BOOL ResetCharset();
 
 
public:
 // ================SQL    (      )================
 //   
 BOOL Select(const char* pszSql, LPFN_RetrieveRecordData lpfnRetrieveRecordData, DWORD dwUserData);
 //   
 BOOL Execute(const char* pszSql);
 //   ,         ,         
 __int64 Insert(const char* pszSql);
 
 
protected:
 MYSQL* m_pMysql;   // mysql       

 //      mysql     
 string m_strDBServer;  // mysql        
 UINT m_uDBPort;   // mysql       
 string m_strDBName;  //      
 string m_strDBUser;  //      
 string m_strDBPwd;   //      
 
};

//         
class CMysqlPool  
{
public:
 CMysqlPool();
 virtual ~CMysqlPool();

 //   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);   
 //      
  void Destroy();
  
public:

 //     mysql  
  CMysqlConn* Get();

 //     mysql  
  void Release(CMysqlConn* pConn);
 
protected:
 HANDLE    m_hSemaphore;       //      
 DWORD    m_dwPoolSize;  //       
 DWORD    m_dwTimeOut;  //   ,   
 CRITICAL_SECTION m_csPool;   //     

 vector<CMysqlConn*> m_vecIdle;   //    
 vector<CMysqlConn*> m_vecBusy;   //    
};

구현 파일:MysqlPool.cpp

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

#pragma comment(lib, "libmysql.lib") //  MysQL    

//////////////////////////////////////////////////////////////////////
// CMysqlConn: mysql      
//////////////////////////////////////////////////////////////////////

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

//     mysql   ,          
BOOL CMysqlConn::Open()
{
 if(m_pMysql)
 {
  mysql_close(m_pMysql); //      
  m_pMysql = NULL;
 }
 
 m_pMysql = mysql_init(NULL);
 if(!m_pMysql)
  return FALSE;
 
 //      
    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;
 }
 
 //     
 char chValue = 1;
 mysql_options(m_pMysql, MYSQL_OPT_RECONNECT, &chValue); 
 mysql_query(m_pMysql,"set names 'gbk'"); 
 
 return TRUE;
}

//        
void CMysqlConn::Close()
{
 if(m_pMysql)
  mysql_close(m_pMysql); //     
 m_pMysql = NULL; 
}

// ping  mysql,       
BOOL CMysqlConn::Ping()
{
 if(m_pMysql)
  return (0 == mysql_ping(m_pMysql));
 return FALSE;
}

//       GBK
BOOL CMysqlConn::ResetCharset()
{
 if(m_pMysql)
  return (0 == mysql_query(m_pMysql, "set names 'gbk'")); 
 return FALSE;
}

// mysql  :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  
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       
//////////////////////////////////////////////////////////////////////

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

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

//   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;
 
 //      
 m_hSemaphore = ::CreateSemaphore(NULL, dwPoolSize, dwPoolSize, NULL);
 if (NULL == m_hSemaphore)
 {
  return FALSE;
 }
 
 //         
 for(DWORD i = 0; i < dwPoolSize; ++i)
 {
  //     mysql     
  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;
 
}

//   mysql   
void CMysqlPool::Destroy()
{
 ::CloseHandle(m_hSemaphore);
 m_hSemaphore = NULL;
 
 //   idle  
 vector<CMysqlConn*>::iterator it;
    for(it = m_vecIdle.begin(); it != m_vecIdle.end(); ++it)
 {
  CMysqlConn* pConn =  *it;
  delete pConn;
 }
 m_vecIdle.clear();
 
 //   busy  
 while(!m_vecBusy.empty())
 {
  CMysqlConn* pConn =  m_vecBusy.back();
  m_vecBusy.pop_back();
  delete pConn;
 } 
}

//  mysql         
CMysqlConn* CMysqlPool::Get()
{
 DWORD dwRet = ::WaitForSingleObject(m_hSemaphore, m_dwTimeOut*1000);
 
 if (WAIT_OBJECT_0 != dwRet)    //   ,         mysql  
 {
  printf("         。\r
"); return NULL; } // CMysqlConn* pConn = NULL; ::EnterCriticalSection(&m_csPool); if (!m_vecIdle.empty()) { pConn = m_vecIdle.back(); // idle m_vecIdle.pop_back(); m_vecBusy.push_back(pConn); // busy } ::LeaveCriticalSection(&m_csPool); if(NULL == pConn) return NULL; // , , mysql_ping // // , if(!pConn->ResetCharset()) { if(!pConn->Open()) return NULL; } printf("==》 : 。\r
"); return pConn; } // mysql void CMysqlPool::Release(CMysqlConn* pConn) { if(NULL == pConn) return; // ::ReleaseSemaphore(m_hSemaphore, 1, NULL); ::EnterCriticalSection(&m_csPool); // Busy vector<CMysqlConn*>::iterator it = find(m_vecBusy.begin(), m_vecBusy.end(), pConn); if(it != m_vecBusy.end()) { printf("POOL SIZE : %d, %d\r
", m_vecIdle.size(), m_vecBusy.size()); m_vecBusy.erase(it); // busy m_vecIdle.push_back(pConn); // idle printf("POOL SIZE : %d, %d\r
", m_vecIdle.size(), m_vecBusy.size()); } ::LeaveCriticalSection(&m_csPool); printf("《== : , 。\r
"); }
테스트 함수

void TestMysqlPool()
{
 //   mysql     
 CMysqlPool mysqlPool;
 if(!mysqlPool.Create("127.0.0.1", 3306, "information_schema", "root", "123456"))
 {
  printf("Create mysql conneticon pool failed.\r
"); return; } // , : ! CMysqlConn* pConn = mysqlPool.Get(); // char* pszSQL = "SELECT * FROM CHARACTER_SETS"; pConn->Select(pszSQL, RetrieveRecordData, 0); // ! : ! mysqlPool.Release(pConn); printf("Test over.\r
"); }
출력 인쇄

총결산
C++를 이용 하여 my sql 데이터베이스 연결 풀 을 어떻게 실현 하 는 지 에 관 한 이 글 은 여기까지 소개 되 었 습 니 다.더 많은 관련 C++my sql 연결 풀 을 실현 하 는 내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 조회 하 시기 바 랍 니 다.앞으로 많은 응원 바 랍 니 다!

좋은 웹페이지 즐겨찾기