Microsoft.Data.SqlClient 連線集區會重複使用經過驗證的實體連線。
SqlConnection.Open 或 OpenAsync 會檢查連線池中是否有可用的連線。
Close、Dispose 或 DisposeAsync 會將其重設並傳回。 此方法避免每次操作都需進行網路連線、認證及會話設定。
Pooling 預設為啟用狀態。 請使用此應用模式:
await using var connection = new SqlConnection(connectionString);
await connection.OpenAsync(cancellationToken);
using var command = new SqlCommand(sql, connection);
await command.ExecuteNonQueryAsync(cancellationToken);
晚開門、早處理,讓池子管理實體連接。 不要讓單一SqlConnection項目全域開放。
了解池金鑰
連線只能從與其相符的集區中被重複使用。 集區金鑰不只包含目的地伺服器。
| Input | 池塘行為 |
|---|---|
| 連接字串 | 文字必須完全一致。 關鍵字順序的差異會產生獨立的池,即使有效設定相同。 |
| Windows 整合式驗證 | Windows 身份是金鑰的一部分。 相同字串在不同識別身分下會建立不同的集區。 |
SqlCredential |
物件實例是金鑰的一部分。 即使包含相同的使用者名稱和密碼,獨立的實例也會建立獨立的集區。 |
SqlConnection.AccessToken |
存取權杖值是金鑰的一部分。 替換代幣字串可能會建立新的集區,並使現有集區中的連線仍以舊代幣通過驗證。 |
SqlConnection.AccessTokenCallback |
回呼是關鍵的一部分。 重複使用同一個回調實例,讓應該共用一個池的連線。 回傳的代幣值不是池金鑰。 |
| 自訂 SSPI 情境提供者 | 提供者實例參與連線設定。 對於應共用同一連線集區的連線,請重複使用同一個提供者執行個體。 |
| 環境交易 | 已登錄的連線在對應的集區內使用交易專屬的子分區。 |
資料庫、驗證模式、加密選項、應用程式名稱、集區選項,以及其他所有連接字串值,都是透過完全相符的字串內容來發揮作用。
建立一個典型的 連接字串 並重複使用。 避免以 Application Name、 Workstation ID或其他關鍵字標示每個請求值。
選擇能夠池化的憑證 API
對於 Microsoft Entra ID 存取權杖,請使用 Microsoft.Data.SqlClient 提供的驗證模式或穩定版的 AccessTokenCallback。
AccessTokenCallback 已於 Microsoft.Data.SqlClient 5.2 中引入。 驅動程式在需要權杖時會呼叫它,並可為重複使用的集區請求更新後的權杖。 保留驅動程式提供的認證參數的確定回調,並重複使用同一個代理實例。
當程式碼直接設定 AccessToken 時:
- 標記字串成為池金鑰的一部分。
- 應用程式自行負責權杖的到期與更新。
- 一個池化的實體連線可能會比用來建立它的代幣還長。
- 如果該代幣池無法安全使用,則在替換過期的代幣後再打電話 ClearPool 。
不要為每個要求建立新的 lambda 回呼函式或憑證物件。 物件身份差異可能會使池子分裂。
Microsoft.Data.SqlClient 7.0 新增了用於自訂 Kerberos 或 NTLM 協商的 SspiContextProvider。 將提供程序視為應用程式層級的連線設定,而非個別請求的狀態。
每個池的規模
這些連線字串選項控制同一個連線集區:
| Keyword | 預設 | Effect |
|---|---|---|
Pooling |
true |
啟用或停用池化。 |
Min Pool Size |
0 |
設定池建立後保留的最少實體連線數。 |
Max Pool Size |
100 |
設定池中物理連線的最大數量。 |
Connect Timeout |
15 秒 | 設定在沒有可用的連線時,Open 會等待多久。 |
Load Balance Timeout |
0 秒 |
當連線回到池時,若其年齡超過設定值,則會丟棄該連線。
Connection Lifetime 是個化名。 |
隨著需求增加,池子會產生連結,直到達到 Max Pool Size。 當所有連線都已使用時,稍後開啟等待連線返回。 若等待時間超過 Connect Timeout,開啟失敗。
檢查前不要加注 Max Pool Size :
- 每條路徑上都配置了每個連線和讀取器。
- 指令和交易都能迅速完成。
- 查詢工作負載未遭到阻塞或飽和。
- 資料庫連線上限可支援
Max Pool Size乘以每個應用程式執行個體中的每個連線池。
正 Min Pool Size 值在閒置期間保持連線暢通。 僅在量測結果顯示有必要使用暖連線時才使用。 它通常對抗可擴展至零、無伺服器自動暫停和可爆發的雲端設計。
在預設為 Load Balance Timeout=0 的情況下,定期清理通常會在約四到八分鐘後移除高於 Min Pool Size 的未使用連線;或者,當連線集區偵測到與伺服器的連線已中斷時,也會將其移除。 請將該時間間隔視為實作上的行為,而非每條連線各自的閒置保證。 連線池不會在每次取出連線前都傳送驗證查詢,因為這樣一次往返會抵消連線池的大部分效益。
處理認證封鎖期間
在認證逾時或其他認證失敗後,池子可能會進入封鎖期。 在此期間,匹配的開放嘗試會重新拋出原始例外,而無需再嘗試驗證。
第一個封鎖期間為五秒。 又一次失敗後,這段時間會加倍到一分鐘。
Pool Blocking Period 控制此行為:
| 價值觀 | 行為 |
|---|---|
Auto |
啟用一般 SQL Server 端點的阻擋,並對已識別的 Azure SQL 端點後綴關閉阻擋。 Vanity DNS 名稱可能不會接收 Azure 的行為。 |
AlwaysBlock |
啟用每個端點的封鎖期間。 |
NeverBlock |
關閉封鎖期。 |
除非應用程式的重試設計需要不同的選擇,否則就保留 Auto 。 停用封鎖時段可能會將認證資料、防火牆或服務中斷問題演變成驗證風暴。
封鎖期間和可設定的重試邏輯是分開的。 在封鎖期間開啟同一池的重試提供者會接收快取的例外。
管理連線存留期與清除
當池子識別到致命錯誤(如故障轉移)時,會自動清除受影響的池子。 池會關閉閒置的連接,並在回來時丟棄已停用的連接。
針對已知的設定或認證界線,使用清除 API:
-
ClearPool 清除與一個
SqlConnection配置相關聯的集區。 - ClearAllPools清除處理序或應用程式定義域中的每個 Microsoft.Data.SqlClient 集區。
池子會關閉清空池中的閒置連接。 池會標記目前正在使用的連線,因此在還回時會丟棄它們。
清空池會讓後續開啟的玩家進行實體登入。 不要把它當作定期維護、一般錯誤處理工具,或是處理連線的替代品。
Load Balance Timeout 提供依年齡漸進的人員流動。 當部署或叢集服務需要讓舊有的實體連線隨著時間逐步淘汰時,請使用它。 確認所選值不會造成過度的硬連接。
了解交易
使用 Enlist=true(預設值)時,在 System.Transactions.Transaction.Current 內開啟的連線會自動登錄至該交易。
當已加入交易的連線關閉後,連線集區會將其放入該交易專屬的子區段。 同一交易下後續開啟的可重複使用。 實體連線要等到交易完成後,才會返回通用連線池。
因此,持續時間過長或已遭捨棄的環境交易可能:
- 請勿將實體連線納入一般集區。
- 在邏輯連線關閉後占用連線池容量。
- 使伺服器鎖和交易狀態維持作用中。
將交易控制在明確範圍內,明確地完成交易,並監控停滯連線。 僅在連線必須保持在環境交易之外時才會設定 Enlist=false 。
防止池碎片化
池碎片化會產生許多小型池,而非少數可重複使用的池。 常見的原因包括:
- 連線字串關鍵字順序或別名差異。
- 每個客戶、使用者、請求或資料庫各有一個連線字串。
- 在多種 Windows 身份下整合認證。
- 新增
SqlCredential、存取權杖回調,或每個請求的 SSPI 提供者實例。 - 每次刷新都會更換的直接存取權杖。
- 高基數應用程式名稱或工作站 ID。
將連線字串 SqlConnectionStringBuilder 正規化並集中建立連線。
若應用程式有意連接多個資料庫或身份,應將所得的池數納入容量規劃中。 不要使用不受信任的資料庫名稱來執行 USE,以免導致集區崩潰。 資料庫隔離、權限、會話狀態及池重置行為必須明確。
將應用程式角色和工作階段狀態納入考量
池會重置可重用的 SQL Server 會話狀態,然後再將實體連線指派給另一個邏輯連線。 應用程式程式碼仍應在其工作單元內設定所需的會話狀態。
使用 sp_setapprole 啟用的 SQL Server 應用程式角色,無法安全地重設以供一般連線集區使用。 建議使用資料庫使用者、內含使用者、角色、資料列層級安全性或其他授權設計。 若應用程式角色無法避免,請使用文件化的 Cookie 反轉模式,或在測試後停用該孤立路徑的池化。
丟棄讀取器、結束或回滾交易,且連線關閉時不要讓指令持續執行。 不要依賴臨時資料表或其他會話狀態能在邏輯連線間存活。
使用雲端代管的集區模式
對於 Azure 應用程式服務、Azure Functions、容器、Kubernetes 及其他水平擴充的主機:
- 計算所有實例、程序、池鍵及副本間可能的資料庫連線。
- 請使用受控識別或穩定的存取權杖回呼函式,而不要在連線物件中輪替權杖字串。
- 除非經量測的冷啟動需求足以證明必須保留工作階段,否則請保持
Min Pool Size=0。 - 預期新實例會從空池開始。
- 在服務相同工作負載的實例間,保持連線字串保持一致。
- 限制連線嘗試次數與重試次數,以避免在故障切換或橫向擴充期間發生同步登入尖峰。
- 為 Azure SQL 與其他受支援的多重位址 TCP 端點設定
MultiSubnetFailover=true。
連線池是應用程式程序本機端專屬的。 它們不會在應用程式實例、容器或主機間共享。
診斷集區運作情形
使用 SqlClient 診斷計數器 來觀察:
- 硬連接與斷開,代表實體伺服器連線。
- 軟連接與斷開,代表池子的檢查與返回。
- 使用中和閒置的集區連線。
- 活躍的泳池團體與泳池。
- 靜止連結。
- 重新回收的連線,應用程式程式碼沒有丟棄邏輯連線。
將用戶端計數器與 SQL Server 會話、等待、阻擋及資源限制相關聯。 池逾時可能代表連線洩漏、查詢緩慢、交易阻塞、過多並發、池碎片化或資料庫容量限制。
使用 事件來源追蹤 來取得針對 pooler 的追蹤記錄。 追蹤很冗長。 啟用有界診斷視窗,並保護所有擷取的連線元資料。
生產檢查清單
- 讓集區化保持啟用。
- 每個工作負載和資料庫都重複使用同一個標準連線字串。
- 在每條路徑上丟棄連線、指令、讀取器和交易。
- 重用憑證、權杖回調及 SSPI 提供者實例。
- 設定有限連線和指令逾時。
- 為所有應用程式執行個體規劃整體連線預算。
- 監控硬連接數、連線池數量、可用連線、停滯和逾時。
- 只有當提供者無法偵測到憑證、令牌或設定邊界,或診斷確認連線仍過時時,才清除池。
- 在正式上線前,先對擴展能力、故障轉移及憑證重新整理行為進行負載測試。