關於SQLSERVER數據庫鏈接池

 


 

 

‘關於數據庫鏈接池你們都據說過或者用過,但真正的瞭解有多少呢?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];
                }
            }            
        }
    }
複製代碼

 

1.如何開啓鏈接池?

只須要鏈接字符串中加入對應的選項便可: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'

 

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];
                }
            }
複製代碼
相關文章
相關標籤/搜索