‘關於數據庫連接池大家都聽說過或者用過,但真正的了解有多少呢?
- 數據連接池如何啟用?有哪些主要的參數?
- 為什么要使用連接池?
- 如何關閉連接池?
- 如何在不開啟新的連接池情況下切換當前數據庫?
- 連接池的生命周期?
- 當數據庫服務器強制關閉連接時會怎么樣?
==============================================================================================================================
首先說明一下測試環境:
數據庫版本:SQL SERVER 12.0.2269.0 [Microsoft SQL Server 2014 Enterprise (64-bit)]
C#版本: Microsoft Visual C# 2015 14.0.25431
客戶端版本:System.Data 4.0.0
首先創建一個數據庫訪問類,便於測試:
public class DbAccepter { /// <summary> /// 數據庫連接 /// </summary> private SqlConnection _conn = new SqlConnection(); /// <summary> /// 數據庫連接字符串 /// </summary> private String _connectionString = ""; /// <summary> /// 數據庫連接字符串 /// </summary> public string ConnectionString { get { return _connectionString; } set { _connectionString = value; _conn.ConnectionString = _connectionString; } } public DataTable GetData(string sql) { string sss = _conn.State.ToString(); using (SqlCommand cmd = new SqlCommand(sql, _conn)) { using (SqlDataAdapter adapter = new SqlDataAdapter(cmd)) { DataSet ds = new DataSet(); _conn.Open(); adapter.Fill(ds); _conn.Close(); return ds.Tables[0]; } } } }
1.如何開啟連接池?
只需要連接字符串中加入對應的選項即可:
private static String _connectionString = "pooling=true;connection lifetime=5;min pool size = 2;max pool size=4;
Data Source = 127.0.0.1; Initial Catalog = tempdb; User ID = test; Password=Sm5lAXQiZ10L";
注意里面和連接池有關的參數:
pooling=true; --表示開啟連接池(默認為開啟)
min pool size = 2 --最小連接池大小:即什么也沒執行初次連接的時候先和數據庫服務建立n個連接
max pool size=4 --最大連接池大小:允許建立的最大連接數,是在需要的時候建立。
舉例說明:min pool size = 2;max pool size=4 ;
點擊按鈕時調用以下代碼執行數據庫腳本。
try { info.Clear(); for (int i = 0; i < num.Value; i++) { Thread th = new Thread(GetCurrentDbName); th.Start(); } } catch (Exception ex) { listboxAdd(ex.Message); }
這里的GetCurrentDbName方法是創建數據庫連接然后執行一段SQL腳本,獲取當前數據庫的名稱然后延時3S,所以每次執行SQL的時間都約為3秒
select db_name(); waitfor delay '00:00:03'; --延遲3秒
這里我們先將並發數設為1,在初次建立連接時會創建2個連接。
可以在數據庫中進行查看:
select * from sysprocesses where hostname='xxx' and loginame='test'
2. 那連接池是和有什么有關呢?
在同一個進程中,只和連接字符串有關,只要連接字符串一樣就會使用同一個連接池。
這里我們將連接字符串改為下圖(只修改了最小數據池):
執行指令后,再觀察一下數據庫的連接信息:
我們發現會多出一個連接信息,可以會懷疑是不是使用的同個連接池。你可以將並發數改為4.
可以看到,這時的連接數變為6,之前的連接字符串占用了兩個,修改后的占用了4個。因為連接池的大小限制為4,所以說明確實是使用了兩個連接池。
當我們的並發請數大於最大連接池數會怎么樣?這里我們修改一下之前的程序代碼,記錄線程調用方法執行的起止時間
9個線程的執行截止時間,可以看出前四的截止時間基本相同,中間的四個大約比前4個晚3S。最后一個比中間四個晚3S。
說明開始有4個線程的數據庫請求獲取到連接池資源,其它線程等待。
這4個線程執行完成后,另4個線程獲的連接池資源,最后一個線程等待真到再次釋放連接池。
那我們再看一下數據庫的連接數仍然為4。說明有多個並行請求時,超過連接池的部分將等待。等待多久會超時呢???
結論是如果想使用連接池,必須使用相同的連接字符串,必須一字不差(我並沒有全部測試)。
3.如何使用相同的連接池訪問不同的數據庫?
在實際開發中我們會訪問同一個服務器中的多個數據庫,但又不想創建過多的連接。如果訪問不同的庫使用不同的連接字符串,那就會產生多個連接池。
如這樣:
pooling=true;connection lifetime=10;min pool size = 2;max pool size=4; Data Source = 127.0.0.1; Initial Catalog = tempdb; User ID = test; Password=Sm5lAXQiZ10L pooling=true;connection lifetime=10;min pool size = 2;max pool size=4; Data Source = 127.0.0.1; Initial Catalog = master; User ID = test; Password=Sm5lAXQiZ10L
這時有兩個辦法:
1.在SQL語句中指定數據庫名稱(不太靠譜)
2.不要重新創建連接,而是使用的相同的連接字符串創建連接后再切換數據庫。實現代碼如下:
using (SqlCommand cmd = new SqlCommand(sql, _conn)) { using (SqlDataAdapter adapter = new SqlDataAdapter(cmd)) { DataSet ds = new DataSet(); _conn.Open(); //這時指向的是tempdb _conn.ChangeDatabase("master"); //切換數據庫 adapter.Fill(ds); _conn.Close(); return ds.Tables[0]; } }