今天,在一本關於大型網站技術架構的書中看到了關於服務端性能優化方面的知識,有一方面是使用數據庫連接池。突然想想自己在從事的編程工作中都是以實現業務爲主,對數據訪問層越來越無知了。所以抽時間看了下 Ado.Net的數據庫連接池。在此分享下,希望對大家有幫助。
首先,程序創建數據庫連接是比較耗時耗資源的工作,之所以會這樣,是因爲連接到數據庫服務器需要經歷幾個漫長的過程:建立物理通道(例如套接字或命名管道),與服務器進行初次握手,分析連接字符串信息,由服務器對連接進行身份驗證,運行檢查以便在當前事務中登記等等。
連接池就是這樣一個容器:它存放了一定數量的與數據庫服務器的物理連接。因此,當我們需要連接數據庫服務器的時候,只需去池(容器)中取出一條空閒的連接,而不是新建一條連接。這樣的話,我們就可以大大減少連接數據庫的開銷,從而提高了應用程序的性能。
那麼作爲一個C#開發人員怎麼使用數據庫連接池呢?實際上,ADO.NET已經爲我們提供了連接池,默認是使用連接池的。
需要說明的是,連接池是具有類別區分的。也就是說,同一個時刻同一應用程序域可以有多個不同類型的連接池。那麼,連接池是如何標識區分的?細緻的講,是由進程、應用程序域、連接字符串以及windows標識(在使用集成的安全性時)共同組成簽名來標識區分的。但對於同一應用程序域來說,一般只由連接字符串來標識區分。當打開一條連接時,如果該條連接的類型簽名與現有的連接池類型不匹配,則創建一個新的連接池。反之,則不創建新的連接池。
下面是3個連接,根據Initial Catalog的字符串不同,會創建不同的連接池。
<span style="font-size:12px;">//創建連接對象1
using (SqlConnection conn1 =
new SqlConnection( "DataSource=(local);Integrated Security=SSPI;Initial Catalog=Northwind"))
{
conn1.Open();
}
//創建連接對象2
using (SqlConnection conn2 =
new SqlConnection( "DataSource=(local);Integrated Security=SSPI;Initial Catalog=pubs"))
{
conn2.Open();
}
//創建連接對象3
using (SqlConnection conn3 =
new SqlConnection( "DataSource=(local);Integrated Security=SSPI;Initial Catalog=Northwind"))
{
conn3.Open();
}</span>
連接池的分配原理
當用戶創建連接請求或者說調用Connection對象的Open時,連接池管理器首先需要根據連接請求的類型簽名找到匹配類型的連接池,然後盡力分配一條空閒連接。具體情況如下:
- 如果池中有空閒連接可用,返回該連接。
- 如果池中連接都已用完,創建一個新連接添加到池中。
- 如果池中連接已達到最大連接數,請求進入等待隊列直到有空閒連接可用。
移除無效連接
無效連接,即不能正確連接到數據庫服務器的連接。對於連接池來說,存儲的與數據庫服務器的連接的數量是有限的。因此,對於無效連接,如不及時移除,將會浪費連接池的空間。其實你不用擔心,連接池管理器已經很好的爲我們處理了這些問題。如果連接長時間空閒,或檢測到與服務器的連接已斷開,連接池管理器會將該連接從池中移除。
回收使用完的連接
當我們使用完一條連接時,應當及時關閉或釋放連接,以便連接可以返回池中重複利用。我們可以通過Connection對象的Close或Dispose方法,也可以通過C#的using語句來關閉連接。(這些是寫代碼的規範)
幾個非常重要屬性
連接池的行爲可以通過連接字符串來控制,主要包括四個重要的屬性:
- Connection Timeout:連接請求等待超時時間。默認爲15秒,單位爲秒。
- Max Pool Size: 連接池中最大連接數。默認爲100。
- Min Pool Size: 連接池中最小連接數。默認爲0。
- Pooling: 是否啓用連接池。ADO.NET默認是啓用連接池的,因此,你需要手動設置Pooling=false來禁用連接池。