Sql Server 连接池
在看緩存的一篇文章中,看到連接池的三個字,來充充電。
原文連接?這篇講了關鍵字
其實我們一直在使用SqlServer的連接池。在連接字符串中,Pooling為是否啟用連接池,默認值為true,表示啟用;可以在鏈接后面加上Pooling=true;的屬性。
與連接池相關的兩個重要參數是 Min Pool Size和 Max Pool Size ,分別是池中的最小連接數和池中的最大連接數,默認值分別是0和100.
在我們創建一個連接的實例,并調用Open()方法時,連接池管理程序會在連接池中找到一個可用的連接;當調用Close()方法時,連接池管理程序又將連接返回到連接池中,以供下一次調用Open()方法時使用.
連接字符串中的 Connection Lifetime 為連接池中的連接設置了生命周期。它的默認值為0。
當連接被返回到池時,將其創建時間與當前時間作比較,如果時間長度(以秒為單位)超出了由?Connection Lifetime?指定的值,該連接就會被銷毀。
這在聚集配置中很有用(用于強制執行運行中的服務器和剛置于聯機狀態的服務器之間的負載平衡)。零(0)值將使連接池具有最大的連接超時。?
通過上面的了解,我們可以看出,即使是最簡單的連接字符串,也在使用連接池。
感覺:“鏈接”就像是一個人,歸于“連接池管理程序”管理,當"外界"需要鏈接實例的時候,回到管理程序中去找一個可以用的;如果這個“鏈接”工作完回來后超過規定時間還有可能被殺死。。。。
asp.net 連接池
數據庫鏈接是一種危險的、昂貴的、有限的資源,特別是在多層Web應用程序中。你必須正確管理你的鏈接,因為你的方法將極大的影響應用程序的整體升級性。
高性能應用程序與使用中的數據源保持最短時間的連接,并且利用性能增強技術,例如連接池。
連接池用于ODBC 的 SQL Server、OLE DB 和 .NET 框架數據提供程序隱式緩沖連接。通過在連接字符串中指定不同的屬性值,可以控制連接池的行為。
連接池概述
數據庫鏈接池使應用程序能夠重用池中的現有鏈接,而不是重復地建立對數據庫的鏈接。這種技術將極大地增加應用程序的可擴展性,因為有限的數據庫鏈接可以為很多的客戶提供服務。此技術也將提高性能,因為能夠避免用于建立新鏈接的巨大時間。
具體來說,大多數 ADO.NET 數據提供程序使用連接池,以提高圍繞 Microsoft 斷開連接的 .NET 結構構建的應用程序的性能。應用程序首先打開一個連接(或從連接池獲得一個連接句柄),接著運行一個或多個查詢,然后處理行集,最后將連接釋放回連接池。如果沒有連接池,這些應用程序將花費許多額外時間來打開和關閉連接。
下面將以SQL Server .NET Framework 數據提供程序連接池為例來說明連接池的一些性能和用法。(另外還有ODBC .NET Framework 數據提供程序連接池、OLE DB .NET Framework 數據提供程序連接池。)
池的創建和分配
當連接打開時,將根據一種精確的匹配算法來創建連接池,該算法會使連接池與連接中的字符串相關聯。每個連接池都與一個不同的連接字符串相關聯。
當新連接打開時,如果連接字符串不精確匹配現有池,則將創建一個新池。
在以下示例中,將創建三個新的 SqlConnection 對象,但只需要使用兩個連接池來管理這些對象。請注意,第一個和第二個連接字符串的差異在于為 Initial Catalog 分配的值
SqlConnection conn = new SqlConnection(); conn.ConnectionString = "Integrated Security=SSPI;Initial Catalog=northwind"; conn.Open(); // Pool A is created. SqlConnection conn = new SqlConnection(); conn.ConnectionString = "Integrated Security=SSPI;Initial Catalog=pubs"; conn.Open(); // Pool B is created because the connection strings differ. SqlConnection conn = new SqlConnection(); conn.ConnectionString = "Integrated Security=SSPI;Initial Catalog=northwind"; conn.Open(); // The connection string matches pool A.連接池一旦創建,直到活動進程終止時才會被毀壞。非活動或空池的維護只需要最少的系統開銷。
在使用SQL Server .NET數據供應器鏈接池時,必須清楚:
鏈接是通過對鏈接字符串精確匹配的法則被池化的。
池化機制對名稱-值對間的空格敏感。例如,下面的兩個鏈接字符串將生成單獨的池,因為第二個字符串包含了一個額外的空字符。
SqlConnection conn = new SqlConnection("Integrated Security=SSPI;Database=Northwind");
conn.Open(); // Pool A is created
SqlConmection conn = new SqlConnection("Integrated Security=SSPI ; Database=Northwind");
conn.Open(); // Pool B is created (extra spaces in string)
總結:1:在鏈接創建時,就會建立一個連接池,相同的鏈接會創建一個連接池;只要鏈接不一樣就會創建出來另外的一個連接池(黃字)
? ? ? ? ? ?2:創建連接池是要消耗資源的,就是這個鏈接不用也占用CPU;
? ? ? ? ? ?3:當這個鏈接在用的時候,其他的請求要等到這個釋放了,才能用,要在連接池中等待;
? ? ? ? ? ?4:連接池貌似有個屬性,可以限制最多多少個鏈接
連接的添加
連接池是為每個唯一的連接字符串創建的。當創建一個池后,將創建多個連接對象并將其添加到該池中,以滿足最小池大小的要求。連接將根據需要添加到池中,直至達到最大池大小。
當請求 SqlConnection 對象時,如果存在可用的連接,則將從池中獲取該對象。若要成為可用連接,該連接當前必須未被使用,具有匹配的事務上下文或者不與任何事務上下文相關聯,并且具有與服務器的有效鏈接。
如果已達到最大池大小且不存在可用的連接,則該請求將會排隊。當連接被釋放回池中時,連接池管理程序通過重新分配連接來滿足這些請求。對 Connection 調用 Close 或 Dispose 時,連接被釋放回池中。
連接的移除
如果連接生存期已過期,或者連接池管理程序檢測到與服務器的連接已斷開,連接池管理程序將從池中移除該連接。請注意,只有在嘗試與服務器進行通信后,才可以檢測到這種情況。如果發現某連接不再連接到服務器,則會將其標記為無效。連接池管理程序會定期掃描連接池,查找已釋放到池中并標記為無效的對象。找到后,這些連接將被永久移除。
如果存在與已消失的服務器的連接,那么即使連接池管理程序未檢測到已斷開的連接并將其標記為無效,仍有可能將此連接從池中取出。當發生這種情況時,將生成異常。但是,為了將該連接釋放回池中,仍必須將其關閉。
選擇池容量
能建立最大極限對于管理幾千用戶同時發出請求的大型系統來說是非常重要的。你需要監視鏈接池及應用程序的性能,以確定系統的最優池容量。最優容量還要依賴于運行SQL Server的硬件。
在開發期間,也許需要減小默認的最大池容量(目前是100)以幫助查找鏈接泄漏。
如果設立了最小池容量,那么當池最初被填充以達到該值時,會導致一些性能損失,盡管最初鏈接的幾個客戶會從中受益。注意,創建新鏈接的過程被序列化了,這就意味著當池最初被填充時,服務器無法處理同時發生的請求。
監視鏈接池化
要監視應用程序對鏈接池化的應用情況,可以使用隨SQL Server發行的Profiler工具,或隨微軟Windows 2000發行的性能監視器。
要利用SQL Server Profiler 監視鏈接池化,操作如下:
1. ? ? ? ? 單擊開始,指向程序,指向Microsoft SQL Server,然后單擊Profiler運行Profiler。
2. ? ? ? ? 在文件菜單中,指向新建,然后單擊跟蹤。
3. ? ? ? ? 提供鏈接內容,然后單擊確定。
4. ? ? ? ? 在跟蹤屬性對話框中,單擊事件標簽。
5. ? ? ? ? 在已選事件類別列表中,確保審核登錄和審核登出事件顯示在安全審核下面。
6. ? ? ? ? 單擊運行開始跟蹤。在鏈接建立時,將會看到審核登錄事件;在鏈接關閉時看到審核登出事件。
要通過性能監視器監視鏈接池化,操作如下:
1. ? ? ? ? 單擊開始,指向程序,指向管理工具,然后單擊性能運行性能監視器。
2. ? ? ? ? 在圖表背景中右擊,然后單擊增加計數器。
3. ? ? ? ? 在性能對象下拉列表框中,單擊SQL Server:通用統計。
4. ? ? ? ? 在出現的列表中,單擊用戶鏈接。
5. ? ? ? ? 單擊增加,然后單擊關閉。
在config中加pooling=false,說明程序中不用連接池。
在config文件的連接字符串中增加max pool size ="1000" 擴大連接池,同時,調整程序,盡量避免多開連接。
?
?Connection Pool 是什么呢 ?(是將已經創建好的數據庫的鏈接,先不關閉,放到連接池中;這樣下次再用的時候可以直接從池中拿取,不需要再創建新的了)
每當程序需要讀寫數據庫的時候。Connection.Open()會使用ConnectionString連接到數據庫,數據庫會為程序建立 一個連接,并且保持打開狀態,此后程序就可以使用T-SQL語句來查詢/更新數據庫。當執行到Connection.Close()后,數據庫就會關閉當 前的連接。很好,一切看上去都是如此有條不紊。?
但是如果我的程序需要不定時的打開和關閉連接,(比如說 ASP.Net 或是 Web Service ),例如當Http Request發送到服務器的時候、,我們需要打開Connection 然后使用Select* from Table 返回一個DataTable/DataSet給客戶端/瀏覽器,然后關閉當前的Connection。那每次都Open/Close Connection 如此的頻繁操作對于整個系統無疑就成了一種浪費。?
ADO.Net Team就給出了一個比較好地解決方法。將先前的Connection保存起來,當下一次需要打開連接的時候就將先前的Connection 交給下一個連接。這就是Connection Pool。
首先當一個程序執行Connection.open()時候,ADO.net就需要判斷,此連接是否支持Connection Pool (Pooling 默認為True),如果指定為False, ADO.net就與數據庫之間創建一個連接(為了避免混淆,所有數據庫中的連接,都使用”連接”描述),然后返回給程序。
如果指定為 True,ADO.net就會根據ConnectString創建一個Connection Pool,然后向Connection Pool中填充Connection(所有.net程序中的連接,都使用”Connection”描述)。填充多少個Connection由Min Pool Size (默認為0)屬性來決定。 例如如果指定為5,則ADO.net會一次與SQL數據庫之間打開5個連接,然后將4個Connection,保存在 Connection Pool中,1個Connection返回給程序。
?
當程序執行到Connection.close() 的時候。如果Pooling 為True,ADO.net 就把當前的Connection放到Connection Pool并且保持與數據庫之間的連接。
同時還會判斷Connection Lifetime(默認為0)屬性,0代表無限大,如果Connection存在的時間超過了Connection LifeTime,ADO.net就會關閉的Connection同時斷開與數據庫的連接,而不是重新保存到Connection Pool中。
(這個設置主要用于群集的SQL 數據庫中,達到負載平衡的目的)。如果Pooling指定為False,則直接斷開與數據庫之間的連接。
?
然后當下一次Connection.Open() 執行的時候,ADO.Net就會判斷新的ConnectionString與之前保存在Connection Pool中的Connection的connectionString是否一致。
(ADO.Net會將ConnectionString轉成二進制流,所 以也就是說,新的ConnectionString與保存在Connection Pool中的Connection的ConnectionString必須完全一致,即使多加了一個空格,或是修改了Connection String中某些屬性的次序都會讓ADO.Net認為這是一個新的連接,而從新創建一個新的連接。所以如果您使用的UserID,Password的認 證方式,修改了Password也會導致一個Connection,如果使用的是SQL的集成認證,就需要保存兩個連接使用的是同一個)。
然后 ADO.net需要判斷當前的Connection Pool中是否有可以使用的Connection(沒有被其他程序所占用),如果沒有的話,ADO.net就需要判斷ConnectionString設 置的Max Pool Size (默認為100),如果Connection Pool中的所有Connection沒有達到Max Pool Size,ADO.net則會再次連接數據庫,創建一個連接,然后將Connection返回給程序。
如果已經達到了 MaxPoolSize,ADO.net就不會再次創建任何新的連接,而是等待Connection Pool中被其他程序所占用的Connection釋放,這個等待時間受SqlConnection.ConnectionTimeout(默認是15 秒)限制,也就是說如果時間超過了15秒,SqlConnection就會拋出超時錯誤(所以有時候如果SqlConnection.open()方法拋 出超時錯誤,一個可能的原因就是沒有及時將之前的Connnection關閉,同時Connection Pool數量達到了MaxPoolSize。)
如果有可用的Connection,從Connection Pool 取出的Connection也不是直接就返回給程序,ADO.net還需要檢查ConnectionString的ConnectionReset屬性 (默認為True)是否需要對Connection 最一次reset。這是由于,之前從程序中返回的Connection可能已經被修改過,比如說使用 SqlConnection.ChangeDatabase method 修改當前的連接,此時返回的Connection可能就已經不是連接當前的Connection String指定的Initial Catalog數據庫了。所以需要reset一次當前的連接。但是由于所有的額外檢查都會增大ADO.net Connection Pool 對系統的開銷。
?
?
?
?
?
?
查看連接數相關
1、獲取SQL Server允許同時用戶連接的最大數
SELECT @@MAX_CONNECTIONS
2、獲取當前指定數據庫的連接信息
?
3、獲取當前SQL服務器所有的連接詳細信息
SELECT * FROM sysprocesses
以上查詢結果包含了:系統進程和用戶進程。
如果只是想查用戶進程的話則需采用下面的方法
4、獲取自上次啟動 SQL Server服務 以來連接或試圖連接的次數
SELECT @@CONNECTIONS
5 ---查看當前數據庫系統所有請求情況.
只列出了我認為比較重要有助于我解決問題的字段。
1 SELECT ds.session_id, 2 ds.status, 3 Db_name(dr.database_id) AS database_name, 4 ds.login_name, 5 ds.login_time, 6 ds.host_name, 7 dc.client_net_address, 8 dc.client_tcp_port, 9 ds.program_name, 10 dr.cpu_time, 11 dr.reads, 12 dr.writes, 13 dc.num_reads, 14 dc.num_writes, 15 ds.client_interface_name, 16 ds.last_request_start_time, 17 ds.last_request_end_time, 18 dc.connect_time, 19 dc.net_transport, 20 dc.net_packet_size, 21 dr.start_time, 22 dr.status, 23 dr.command, 24 dr.blocking_session_id, 25 dr.wait_type, 26 dr.wait_time, 27 dr.last_wait_type, 28 dr.wait_resource, 29 dr.open_transaction_count, 30 dr.percent_complete, 31 dr.granted_query_memory 32 FROM Sys.dm_exec_requests dr WITH(nolock) 33 RIGHT OUTER JOIN Sys.dm_exec_sessions ds WITH(nolock) 34 ON dr.session_id = ds.session_id 35 RIGHT OUTER JOIN Sys.dm_exec_connections dc WITH(nolock) 36 ON ds.session_id = dc.session_id 37 WHERE ds.session_id > 50 38 ORDER BY ds.program_name View Code用戶連接數
?
?
?
?主函數:
方法:
?
轉載于:https://www.cnblogs.com/ZkbFighting/p/9564648.html
總結
以上是生活随笔為你收集整理的Sql Server 连接池的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Luogu 3008 [USACO11J
- 下一篇: python编码与存储读取数据(数组字典