關於SQLSERVER數據庫連接池


 


 

 

‘關於數據庫連接池大家都聽說過或者用過,但真正的了解有多少呢?

 

  • 數據連接池如何啟用?有哪些主要的參數?
  • 為什么要使用連接池?
  • 如何關閉連接池?
  • 如何在不開啟新的連接池情況下切換當前數據庫?
  • 連接池的生命周期?
  • 當數據庫服務器強制關閉連接時會怎么樣?

 

==============================================================================================================================

首先說明一下測試環境:

數據庫版本: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];
                }
            }
復制代碼


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM