‘關於數據庫鏈接池你們都據說過或者用過,但真正的瞭解有多少呢?sql
==============================================================================================================================數據庫
首先說明一下測試環境:服務器
數據庫版本: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.0spa
首先建立一個數據庫訪問類,便於測試:線程
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]; } } } }
只須要鏈接字符串中加入對應的選項便可:code
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";
注意裏面和鏈接池有關的參數:htm
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'
在同一個進程中,只和鏈接字符串有關,只要鏈接字符串同樣就會使用同一個鏈接池。
這裏咱們將鏈接字符串改成下圖(只修改了最小數據池):
執行指令後,再觀察一下數據庫的鏈接信息:
咱們發現會多出一個鏈接信息,能夠會懷疑是否是使用的同個鏈接池。你能夠將併發數改成4.
能夠看到,這時的鏈接數變爲6,以前的鏈接字符串佔用了兩個,修改後的佔用了4個。由於鏈接池的大小限制爲4,因此說明確實是使用了兩個鏈接池。
當咱們的併發請數大於最大鏈接池數會怎麼樣?這裏咱們修改一下以前的程序代碼,記錄線程調用方法執行的起止時間
9個線程的執行截止時間,能夠看出前四的截止時間基本相同,中間的四個大約比前4個晚3S。最後一個比中間四個晚3S。
說明開始有4個線程的數據庫請求獲取到鏈接池資源,其它線程等待。
這4個線程執行完成後,另4個線程獲的鏈接池資源,最後一個線程等待真到再次釋放鏈接池。
那咱們再看一下數據庫的鏈接數仍然爲4。說明有多個並行請求時,超過鏈接池的部分將等待。等待多久會超時呢???
結論是若是想使用鏈接池,必須使用相同的鏈接字符串,必須一字不差(我並無所有測試)。
在實際開發中咱們會訪問同一個服務器中的多個數據庫,但又不想建立過多的鏈接。若是訪問不一樣的庫使用不一樣的鏈接字符串,那就會產生多個鏈接池。
如這樣:
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]; } }