利用物件池優化資料庫操作

2022-02-02 13:32:58 字數 2565 閱讀 7788

說到物件池,大家都不陌生。很多人都實現過,網上的**也滿天飛。說到連線池,更是誰人不知,哪家不曉。也有不少人自己實現了連線池,試圖對資料訪問進行優化。歸納了一下,比較常見的思路如下:

1.                   資料庫連線的開啟比較耗費資源,如果能避免重複的開關,可以提高效率。

2.                   如果有乙個一直開啟資料庫連線,直到程式結束其生命才隨之結束。長時間開啟並重複使用將導致連線物件的不穩定。

3.                   無法保證開啟的連線一點問題都不出。

4.                   自動化管理資料庫連線,解決頻繁建立、分配、釋放帶來的問題

然而本人認為,這些擔心相對來說並不是首要的。微軟在.net framework平台下既然推薦使用斷開模式,按照微軟的作風,必然有乙個適當的解決方案來。首先ado.net本身實現了連線池,自動管理資料庫連線的生命週期(雖然如果不加控制,隨意開啟連線,也會有池被填滿的時候),其次ado.net的連線池也解決了資料庫連線反覆開啟的效率問題。本人認為:雖然常見的連線池都以控制連線的例項數為目標,但池中的元素其實是共享的,也無法控制併發的運算元,並不見得就能為效能帶來什麼本質的提高。在資料庫操作中有乙個更重要的東西:控制同一時間的併發運算元。

首先,來看看ado.net的工作方式。ado.net在資料訪問上提供了2種方式:1、連線模式:一般採用dbdatareader對資料進行讀取,讀取的過程中,資料庫連線始終是開啟的。在讀取資料前,開啟資料庫連線。讀取結束後在關閉資料庫連線。2、斷開模式:利用dbdataadapter將資料一次性取出,填充到dataset中,然後關閉資料庫連線,dataset中的資料和資料庫是完全斷開的。由dbdataadpater在是獲取資料前,判斷資料庫連線是否開啟,如果處於關閉狀態,則將連線開啟,填充完dataset之後,再將資料庫連線關閉。如果連線在獲取資料之前已經開啟,則不開啟連線,填充完dataset後也不將連線關閉。因此ado.net的工作方式可以歸納為以下流程:1、開啟連線。2、執行sql語句返回結果。3、關閉連線。可以說這3個步驟組成了.net下資料操作的標準模式。雖然資料操作只是在重複這3個 基本步驟,但是在單執行緒和多執行緒的應用場合下實現的細節也有所不同。單執行緒應用開發時,常用的做法是整個應用程式共享乙個資料庫連線;由於乙個應用程式 中,使用者同一時間只能進行一次資料庫操作,因此這種方法是可行的。而進行多執行緒應用開發時,由於是多執行緒併發運算元據庫,因此每次資料庫操作都例項化乙個 資料庫連線,然後再執行標準的3個步驟。

從ado.net的工作方式不難看出,如果同時進行的多個資料操作,共享乙個資料庫連線,是絕對不允許的。雖然ado.net提供了mars(即:multiple active result sets)來解決這個問題,在資料庫連線字串中加入「multipleactiveresultsets=true」。但並不是所有資料庫都支援mars,常用的sql server2000資料庫就是乙個例子,而且啟用mars會大大降低系統的效能。因此當資料庫不支援mars時或出於效能上的考慮又或者不是讀取而是進行寫操作,最常用的做法就是每乙個資料操作都例項化乙個資料庫連線。

然 而,看似合理的做法又引來了新的問題。首先伺服器資源是有限的,每次資料操作都例項化乙個連線都會占用伺服器資源,特別是在長時間的資料訪問操作上。如果 例項化並開啟了乙個資料連線,但忘記關閉,將占用伺服器的連線直到垃圾**機制自動**的時候才會釋放當前占用的連線,容易造成所謂的連線洩露。其次,客 戶端進行非同步呼叫的時候往往無法**併發的數量,無限制發起非同步操作並同時進行將導致伺服器超負荷工作,不僅沒有起到優化的作用,還帶來了更多負面的影響 (如:連線超時、響應變慢、記憶體不足等一些列問題)。

通過簡單的測試可以得到一下結果:即使sql語句執行時間較短,同時進行大量的併發資料庫操作,但不加控制,伺服器基本就當機了。當sql語句執行時間較長時,可能希望利用併發的非同步操作來優化效率,如果不加控制,實際結果往往是連線超時的機率大大增加,卻不見得能帶來更高的效率。或者說乙個客戶端開始發飆後,其他的客戶端基本就無法連上了。

總結起來,必須用乙個比較合理的手段來控制例項化的連線數,同時又能控制併發的資料庫運算元。實現乙個物件池,池中的元素都是以獨佔方式取出。池的策略分為2種:1、速度優先:只要有空閒的元素就直接使用。2、使用次數優先:在已使用的元素中選擇使用次數最少的。從池中獲取可用的資料庫連線時,首先判斷是否有已初始化的空閒連線,其次判斷是否還有空位能容納新的連線。如果前二者都無法滿足,則進入等待並利用sleep暫 停當前線程,直到有元素空閒。在物件池初始化的同時,啟動乙個輪詢執行緒,用於定時對物件池進行執行清理工作,如:在作為連線池時可以關閉超時的連線,釋放 未使用的連線。具體使用時,只要簡單將原來例項化乙個dbconnection改為從池中獲取乙個可用的連線。並在使用完成之後將連線歸還給池。由於池中 的每個元素都是獨佔的,當池中沒有空閒的元素時就必須等待,直到有空閒的元素出現。因此,設定合適的池大小,在一定程度上等於限制了併發的運算元。

恰當地使用物件池技術,能有效地改善應用程式的效能。目前,物件池技術已得到廣泛的應用(如:對於web、網路和資料庫等,一般都會採用物件池技術),但不應濫用。ado.net本身實現了連線池,並為我們提供了乙個高效、健壯的機制。在ado.net開發時應該將主要的精力放在如何控制併發的數量和優化sql語句上以及事務的處理上。

最後,丟乙個土了吧唧的物件池工作流程圖,讓人批鬥^_^ 。

物件池及資料庫連線物件池

objectpool類 物件池 using system using system.collections.generic using system.text using system.timers using system.collections namespace objectpool 建立乙個...

優化資料庫物件

1.優化表的資料型別 在mysql 中,可以使用函式procedure analyse 對當前應用的表進行分析,該函式可以對資料表中列的資料型別 提出優化建議,使用者可以根據應用的實際情況酌情考慮是否實施優化。使用方法 select from tbl name procedure analyse s...

DataSnap資料庫連線池,資料集物件池的應用

傳統的應用伺服器的開發往往是在servermethods單元中拖放一堆tdataset,tdatasetprovider控制項,這是乙個最簡單粗暴的開發方向,往往會造成服務端程式檔案的臃腫 服務執行期間記憶體資源消耗過大的問題。因此這種往應用伺服器中拖放一堆tdataset,tdatasetprov...