




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
1、 如何創(chuàng)建數(shù)據(jù)庫連接池一個(gè)基于libmysql的MySQL數(shù)據(jù)庫連接池示例1、 一般架構(gòu)說明圖1 架構(gòu)層次圖 一般應(yīng)用系統(tǒng)數(shù)據(jù)庫訪問模塊可大致分為兩層,一層是對(duì)數(shù)據(jù)庫連接、連接池和結(jié)果集等直接對(duì)數(shù)據(jù)庫的操作的封裝,由于libmysql提供的庫函數(shù)是直接操作數(shù)據(jù)庫的,所以這一層在本質(zhì)上是直接操作數(shù)據(jù)庫的一層;二是可以根據(jù)系統(tǒng)業(yè)務(wù)功能將系統(tǒng)與數(shù)據(jù)庫的交互劃分為幾個(gè)子塊,提供給系統(tǒng)其它模塊與數(shù)據(jù)庫交互的接口。如果是C/S結(jié)構(gòu)的系統(tǒng),客戶端與數(shù)據(jù)庫的交互還可以通過諸如RPC(Remote Procedure Call Protocol 遠(yuǎn)程過程調(diào)用協(xié)議)等協(xié)議調(diào)用服務(wù)端RPC處理模塊來進(jìn)行。 如上的設(shè)
2、計(jì)一是隔離了外界與數(shù)據(jù)庫的直接交互,提高了數(shù)據(jù)安全性;二是對(duì)libmysql提供的數(shù)據(jù)庫操作接口眾多,統(tǒng)一類操作有多種不同的方式,各自適用的場合不同,對(duì)其進(jìn)行了整合,是為使其更適合本系統(tǒng),提高了系統(tǒng)的穩(wěn)定性和可用性,同時(shí)使上層對(duì)數(shù)據(jù)庫的操作更為方便;三是按系統(tǒng)功能劃分子模塊降低了系統(tǒng)的耦合度,提高了系統(tǒng)的可擴(kuò)展性。 另外,數(shù)據(jù)庫直接交互層也分為三個(gè)小塊,這樣做的目的也是為了降低系統(tǒng)耦合度。其中數(shù)據(jù)庫連接管理塊僅負(fù)責(zé)數(shù)據(jù)庫連接的維持及相應(yīng)查詢事物處理。數(shù)據(jù)庫連接池管理塊則是負(fù)責(zé)在系統(tǒng)初始化時(shí)創(chuàng)建一定數(shù)量的數(shù)據(jù)庫連接,實(shí)際上就是建立兩個(gè)連接隊(duì)列(一個(gè)在用連接隊(duì)列和一個(gè)空閑連接隊(duì)列)并維護(hù)這兩個(gè)隊(duì)列
3、。對(duì)于連接池的建立是為了避免在每一次操作數(shù)據(jù)庫時(shí)都要建立數(shù)據(jù)庫連接和釋放數(shù)據(jù)庫連接等耗時(shí)操作,提高系統(tǒng)性能。數(shù)據(jù)結(jié)果集的處理是專門負(fù)責(zé)將查詢返回的結(jié)果按上層要求的方式提供給上層使用。2、 數(shù)據(jù)庫連接類的實(shí)現(xiàn) 本類主要是實(shí)現(xiàn)數(shù)據(jù)庫連接的建立和釋放,數(shù)據(jù)庫選擇,SQL語句的執(zhí)行,事務(wù)的提交和回滾及數(shù)據(jù)庫錯(cuò)誤信息的獲取等功能。其中數(shù)據(jù)庫連接的建立與釋放及查詢語句的執(zhí)行是本節(jié)敘述的重點(diǎn)。在libmysql提供的庫中使用mysql_real_connect()可與MySQL數(shù)據(jù)庫建立連接,但在這之前還需要對(duì)MYSQL實(shí)例進(jìn)行初始化,其中MYSQL為MySQL的數(shù)據(jù)庫連接句柄,具體實(shí)現(xiàn)過程如下。 a、使用
4、mysql_init()創(chuàng)建MYSQL句柄實(shí)例; b、根據(jù)數(shù)據(jù)庫主機(jī)地址、用戶名、用戶密碼、數(shù)據(jù)庫名及端口號(hào)等連接信息使用mysql_real_connect()接口為MYSQL句柄實(shí)例建立數(shù)據(jù)庫連接; c、為已經(jīng)建立數(shù)據(jù)庫連接的MYSQL句柄實(shí)例選擇字符集。 需要注意的是,當(dāng)應(yīng)用程序服務(wù)器和數(shù)據(jù)庫服務(wù)器不在同一主機(jī)時(shí),新安裝的MySQL數(shù)據(jù)庫處于安全考慮是不允許遠(yuǎn)程連接的,這就需要為相應(yīng)的用戶賦予遠(yuǎn)程訪問的權(quán)限,可采用MySQL命令:sql view plaincopyGRANT EXECUTE ON DBName.TableName TO UserName192.168.1.1 IDENT
5、IFIED BY UserPassword; 其中“192.168.1.1”為遠(yuǎn)程主機(jī)的IP地址,使用“%”表示接受所有IP主機(jī)的遠(yuǎn)程訪問。當(dāng)然出于數(shù)據(jù)安全考慮,需要慎重執(zhí)行。最終實(shí)現(xiàn)連接建立的代碼如下:cpp view plaincopyint CDBConnect:ConnectDB(const char *host, const char *user, const char *password, const char *db, unsigned int port) if (m_pMySql != NULL) if( NULL != pLC ) pLC-Trace( _FILE_, _LI
6、NE_, m_pMySql 已經(jīng)初始化n); return DATABASE_NOERROR; m_pMySql = mysql_init(MYSQL*)NULL); if (m_pMySql = NULL) if( NULL != pLC ) pLC-Fatal( _FILE_, _LINE_, m_pMySql 初始化失敗n); return DATABASE_ERROR_INIT_POOL; if (!mysql_real_connect(m_pMySql, host, user, password, db, port,NULL,0) if( NULL != pLC ) pLC-Fata
7、l( _FILE_, _LINE_, 數(shù)據(jù)庫連接失敗,%sn, GetLastErrorMsg(); int iRet = mysql_errno(m_pMySql); printf( errno = %dn, iRet ); if (iRet = 1045) return DATABASE_ERROR_USERORPASSWORD; return DATABASE_ERROR_GET_CONNECTION; if (mysql_set_character_set(m_pMySql, gbk) != 0) if( NULL != pLC ) pLC-Error( _FILE_, _LINE_,
8、 數(shù)據(jù)庫字符集設(shè)置失敗,%sn, GetLastErrorMsg(); return DATABASE_POOL_ERROR_SET_CHARACTER; return DATABASE_NOERROR; void CDBConnect:Release() delete this; void CDBConnect:CloseConnect() m_ResultSet.Close(); if (m_pMySql != NULL) mysql_close(m_pMySql); m_pMySql = NULL; void CDBConnect:CloseQuery() m_ResultSet.Clo
9、se(); int CDBConnect:ConnctionTest() if (m_pMySql = NULL) if( NULL != pLC ) pLC-Debug( _FILE_, _LINE_, m_pMySql 沒有初始化n); return DATABASE_ERROR_INIT_POOL; else return mysql_ping(m_pMySql); int CDBConnect:SelectDB(const char *szDB) if (m_pMySql = NULL) if( NULL != pLC ) pLC-Debug( _FILE_, _LINE_, m_pM
10、ySql 沒有初始化n); return DATABASE_ERROR_INIT_POOL; if (mysql_select_db(m_pMySql,szDB) if( NULL != pLC ) pLC-Error( _FILE_, _LINE_, 選擇數(shù)據(jù)庫失敗,%sn, GetLastErrorMsg(); return -1/*DATABASE_POOL_ERROR_SELECT_DATABASE*/; else return DATABASE_NOERROR; int CDBConnect:AutoCommit(bool mode) if (m_pMySql = NULL) if(
11、 NULL != pLC ) pLC-Debug( _FILE_, _LINE_, m_pMySql 沒有初始化n); return DATABASE_ERROR_INIT_POOL; return mysql_autocommit(m_pMySql, mode); int CDBConnect:Commite() if (m_pMySql = NULL) if( NULL != pLC ) pLC-Debug( _FILE_, _LINE_, m_pMySql 沒有初始化n); return DATABASE_ERROR_INIT_POOL; return mysql_commit(m_pM
12、ySql); int CDBConnect:RollBack() if (m_pMySql = NULL) if( NULL != pLC ) pLC-Debug( _FILE_, _LINE_, m_pMySql 沒有初始化n); return DATABASE_ERROR_INIT_POOL; return mysql_rollback(m_pMySql); PIDBResultSet CDBConnect:ExcuteQuery(const char *szSql) if (m_pMySql = NULL) if( NULL != pLC ) pLC-Debug( _FILE_, _LI
13、NE_, m_pMySql 沒有初始化n); return NULL; if(mysql_query(m_pMySql, szSql) if( NULL != pLC ) pLC-Error( _FILE_, _LINE_, 讀數(shù)據(jù)庫失敗,%sn, GetLastErrorMsg(); return NULL; m_ResultSet.Reset(mysql_store_result(m_pMySql); return &m_ResultSet; int CDBConnect:ExcuteSql(const char *szSql) if (m_pMySql = NULL) if( NULL
14、!= pLC ) pLC-Debug( _FILE_, _LINE_, m_pMySql 沒有初始化n); return DATABASE_ERROR_INIT_POOL; if(mysql_query(m_pMySql,szSql) if( NULL != pLC ) pLC-Error( _FILE_, _LINE_, SQL語句執(zhí)行失敗,%sn, GetLastErrorMsg(); return DATABASE_ERROR_EXCUTE_QUERY; return mysql_affected_rows(m_pMySql); int CDBConnect:ExcuteRealSql(
15、const char *szSql, unsigned long ulSqlLen ) /這里添加參數(shù)檢查語句 if( ulSqlLen Debug( _FILE_, _LINE_, m_pMySql 沒有初始化n); return DATABASE_ERROR_INIT_POOL; unsigned long CDBConnect:EscapeRealToString( char *pDst, const char *pSrc, unsigned long ulSrcLen ) /這里添加參數(shù)檢查代碼 if( ulSrcLen = 0 ) /這里添加日志打印語句 if (m_pMySql =
16、 NULL) /這里添加日志打印語句 return DATABASE_ERROR_INIT_POOL; return mysql_real_escape_string(m_pMySql,pDst, pSrc, ulSrcLen); 3、 數(shù)據(jù)庫連接池類的實(shí)現(xiàn) 本類實(shí)現(xiàn)了連接池的建立和銷毀,連接池運(yùn)行狀態(tài)信息的獲取,從連接池中取出可用數(shù)據(jù)庫連接及將短時(shí)間內(nèi)不再使用的數(shù)據(jù)庫連接放回連接池等操作。本類的架構(gòu)實(shí)現(xiàn)關(guān)系到數(shù)據(jù)庫的訪問速度,攸關(guān)整個(gè)系統(tǒng)性能。同時(shí)為了維護(hù)連接池的安全性,保證在同一時(shí)間內(nèi)只有一個(gè)線程能操作連接池,同一個(gè)連接也只能被一個(gè)線程使用,涉及到設(shè)置臨界區(qū)和信號(hào)量等操作,下面將逐一詳述。
17、 a、數(shù)據(jù)結(jié)構(gòu)描述cpp view plaincopytypedef std:list CONNECTION_HANDLE_LIST; typedef std:list:iterator ITER_CONNECTION_HANDLE_LIST; class CDBConnectPool private: string m_host; /主機(jī) string m_user; /用戶名 string m_password; /密碼 string m_db; /數(shù)據(jù)庫名 unsigned int m_port; /端口 unsigned int m_connNum; /連接池的大小 CONNECTIO
18、N_HANDLE_LIST m_lsBusyList; /正在使用的連接句柄,隊(duì)列模型 CONNECTION_HANDLE_LIST m_lsIdleList; /未使用的連接句柄,隊(duì)列模型 CRITICAL_SECTION m_csList; /臨界值句柄 HANDLE m_hSemaphore; /信號(hào)量句柄 static CDBConnectPool *pConnPool; /單例模式 b、連接池的建立 在連接池建立時(shí),首先應(yīng)跟據(jù)用戶要求建立連接的數(shù)量創(chuàng)建相應(yīng)數(shù)量信號(hào)量,在逐個(gè)新建連接并放入空閑連接隊(duì)列,其中任何一個(gè)連接創(chuàng)建失敗都將導(dǎo)致整個(gè)連接池的建立失敗。具體實(shí)現(xiàn)如下:cpp view
19、 plaincopyint CDBConnectPool:Connect() /同時(shí)打開connNum個(gè)連接 int ret = 0; if (m_hSemaphore != NULL) return DATABASE_ERROR; m_hSemaphore = CreateSemaphore(NULL, m_connNum, m_connNum, NULL); if (m_hSemaphore = NULL) return DATABASE_POOL_ERROR_INIT_SEMAPHORE; int i = 0; for ( i=0; iConnectDB(m_host.c_str(),
20、m_user.c_str(), m_password.c_str(), m_db.c_str(), m_port); if(retCloseConnect(); pConn-Release(); m_lsBusyList.clear(); for (iter = m_lsIdleList.begin(); iter != m_lsIdleList.end(); iter+) PIDBConnect pConn = *iter; if( pConn != NULL ) pConn-CloseConnect(); pConn-Release(); ; m_lsIdleList.clear(); i
21、f( m_hSemaphore != NULL ) CloseHandle(m_hSemaphore); m_hSemaphore = NULL; d、從連接池中獲取可用連接 在從連接池中取出連接時(shí),首先等待信號(hào)量,直到有可用連接或者等待超時(shí)返回(避免線程死鎖),然后進(jìn)入臨界區(qū),即對(duì)兩個(gè)隊(duì)列的操作區(qū)域,防止在取連接時(shí)有其它線程也來去連接或是放連接回池,接著離開臨界區(qū),通知其它等待線程可操作臨界區(qū)。另外比較重要的一點(diǎn)是,為確保我們?nèi)〉降倪B接是真正可用的連接,在從空閑連接隊(duì)列中取出連接并放入忙連接隊(duì)列后需要測試我們得到的連接是否連通,未連通時(shí)應(yīng)嘗試重連,若重連依然失敗,則應(yīng)返回空。實(shí)現(xiàn)代碼如下:c
22、pp view plaincopyPIDBConnect CDBConnectPool:GetConnection(int iTimeOut) int ret; PIDBConnect pConn = NULL; DWORD dwWaitResult; dwWaitResult = WaitForSingleObject(m_hSemaphore, iTimeOut); if (dwWaitResult != WAIT_OBJECT_0) return NULL; EnterCriticalSection(&m_csList); if (m_lsIdleList.size() 0) pConn
23、 = m_lsIdleList.front(); m_lsIdleList.pop_front(); m_lsBusyList.push_back(pConn); else pConn = NULL; LeaveCriticalSection(&m_csList); if (pConn-ConnctionTest() != 0) char strError1000 = 0; strncpy(strError, pConn-GetLastErrorMsg(), 999); strError999 = 0; pConn-CloseConnect(); ret = pConn-ConnectDB(m
24、_host.c_str(), m_user.c_str(), m_password.c_str(), m_db.c_str(), m_port); if (ret CloseQuery(); pConn-AutoCommit(true); EnterCriticalSection(&m_csList); ReleaseSemaphore(m_hSemaphore, 1, NULL); m_lsBusyList.remove(pConn); m_lsIdleList.push_back(pConn); LeaveCriticalSection(&m_csList); 4、 數(shù)據(jù)庫結(jié)果集類的實(shí)現(xiàn)
25、本類主要實(shí)現(xiàn)對(duì)查詢返回結(jié)果的一系列操作,包含查找指定數(shù)據(jù)、取得記錄數(shù)、獲得下一條記錄及根據(jù)字段名或是字段在結(jié)果集中的ID獲取字段等。直接給出源碼如下:頭文件:cpp view plaincopy/ / Copyright (C), 2011 / file DBResultSet.h / brief DATABASE數(shù)據(jù)庫結(jié)果集接口 / author hkp(horace20) / version 1.1 / date 2011 / #ifndef _DATABASE_RECORD_SET_ #define _DATABASE_RECORD_SET_ #pragma comment(lib,li
26、bmysql.lib) #pragma warning(disable: 4786) /Disable warning messages #include #include using namespace std; namespace Database class CDBResultSet : public IDBResultSet friend class CDBConnect; /友元類 private: MYSQL_RES* m_pMyQuery; /結(jié)果集 MYSQL_ROW m_currentRow; /基類 unsigned int m_fieldCount; /=0 正常 0異常
27、 / DB_ROW_CONUT GetRowNum(); / / brief 取得下一條記錄 / paramin 無 / paramout 無 / return TRUE 正常 FALSE 異常 / bool GetNextRecod(); / / brief 得到字段 / paramin 字段下標(biāo) / paramout 取得有符號(hào)整型值 / return =0 正常 0異常 / int GetFiled(int filedId, int& value); / / brief 得到字段 / paramin 字段下標(biāo) / paramout 取得無符號(hào)整型值 / return =0 正常 0異常 / int GetFiled(int file
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 合同范例在下
- 廈門學(xué)校食堂承包合同范例
- 臨時(shí)土地合同范本
- 吉他老師合同范本
- 2025年麻風(fēng)二聯(lián)苗合作協(xié)議書
- 債權(quán)協(xié)議合同范本
- 綠化設(shè)計(jì)苗木合同范本
- 代辦貸款定金合同范例
- 勞動(dòng)合同范本講解
- 發(fā)票業(yè)務(wù)合同范本
- 物體打擊傷亡事故應(yīng)急處置卡
- 2024-2030年中國飛機(jī)AFP和ATL復(fù)合材料行業(yè)市場發(fā)展趨勢與前景展望戰(zhàn)略分析報(bào)告
- 七年級(jí)英語上冊(cè)(人教版2024)新教材解讀課件
- 中醫(yī)食療藥膳學(xué)智慧樹知到答案2024年四川護(hù)理職業(yè)學(xué)院
- NB/T 11431-2023土地整治煤矸石回填技術(shù)規(guī)范
- 中醫(yī)師承跟師筆記50篇
- 聚乳酸-標(biāo)準(zhǔn)規(guī)程
- 任務(wù)型閱讀-小升初英語專項(xiàng)練習(xí)(譯林版三起)
- 部編版語文二年級(jí)下冊(cè)第三單元教材解讀大單元集體備課
- 七年級(jí)地理上冊(cè)期末試卷(可打印)
- ISO28000:2022供應(yīng)鏈安全管理體系
評(píng)論
0/150
提交評(píng)論