如何主動清空 .NET 數(shù)據(jù)庫連接池?
前言
一般我們的項目中會使用1到2個數(shù)據(jù)庫連接配置,同程藝龍的數(shù)據(jù)庫連接配置被收攏到統(tǒng)一的配置中心,由DBA統(tǒng)一維護(hù),業(yè)務(wù)方通過某個配置字符串拿到的是開箱即用的Connection對象。

DBA能在對業(yè)務(wù)方無侵入的情況下,給業(yè)務(wù)方切換備份數(shù)據(jù)庫,之后DBA要求舊連接池必須立即被清空。
那么問題來了:?能不能立即清空.NET連接池?
注意我用得是清空,而不是釋放連接。
如果有同學(xué)不知道DBA做這個要求的目的,那我啰嗦一下:
應(yīng)用程序不再使用舊連接時,理論上你的連接池要被完全清空,因為單純的釋放連接,只會讓連接池中的Connection處于Sleep狀態(tài),依舊維持了短時間的物理連接,這個短時間其實是不必要的占用,影響了舊連接數(shù)據(jù)庫的吞吐量。
連接池知識背景
回答這個問題之前, 我們還是先研究一下.NET數(shù)據(jù)庫連接池。
1、.NET數(shù)據(jù)庫連接池的背景
數(shù)據(jù)庫連接是一個耗時的行為,大多數(shù)應(yīng)用程序只使用1到幾種數(shù)據(jù)庫連接,為了最小化打開連接的成本,ado.net使用了一種稱為連接池的優(yōu)化技術(shù)。
2、.NET 數(shù)據(jù)庫連接池的表現(xiàn)
數(shù)據(jù)庫連接池減少了必須打開新連接的次數(shù),池程序維護(hù)了數(shù)據(jù)庫物理連接。通過為每個特定的連接配置保持一組活動的連接對象來管理連接。每當(dāng)應(yīng)用程序嘗試Open連接,池程序就會在池中找到可用的連接,如果有則返回給調(diào)用者;
應(yīng)用程序Close連接對象時,池程序?qū)⑦B接對象返回到池中(Sleep), 這個連接可以在下一次Open調(diào)用中重用。看黑板,下面是這次的重點:
3、.NET是如何形成數(shù)據(jù)庫連接池的?
進(jìn)程相同、
連接字符串相同、
連接字符串關(guān)鍵key順序相同。
(連接字符串提供的關(guān)鍵字順序不同也將被分到不同的池)。連接池中的可用連接的數(shù)量由連接字符串
Max Pool Size決定。在一個應(yīng)用程序中,有如下代碼:using?(SqlConnection?connection?=?new?SqlConnection(????
??"Integrated?Security=SSPI;Initial?Catalog=Northwind"))????
????{????
????????connection.Open();??
????????//?Pool?A?is?created.????
????}????
????
using?(SqlConnection?connection?=?new?SqlConnection(????
??"Integrated?Security=SSPI;Initial?Catalog=pubs"))????
????{????
????????connection.Open();??
????????//?Pool?B?is?created?because?the?connection?strings?differ.????
????}????
????
using?(SqlConnection?connection?=?new?SqlConnection(????
??"Integrated?Security=SSPI;Initial?Catalog=Northwind"))????
????{????
????????connection.Open();??
????????//?The?connection?string?matches?pool?A.????
????}????
上面創(chuàng)建了三個Connection對象,但是只形成了兩個數(shù)據(jù)庫連接池。還是以上代碼,如果有兩個相同的應(yīng)用程序,理論上就形成了四個數(shù)據(jù)庫連接池。
4、連接池中的連接什么時候被移除?
連接池中的連接空閑4-8 分鐘,池程序會移除這個連接。應(yīng)用程序下線,連接池直接被清空。
如何主動清空.NET連接池
有了以上知識背景,我們再來回顧一下DBA的要求,切換數(shù)據(jù)庫連接配置的時候,清空原連接池。.NET提供了?ClearAllPools、ClearPool靜態(tài)方法用于清空連接池。
? ClearAllPools:? ? ? 清空與這個DBProvider相關(guān)的所有連接池
? ClearPool(DBConnection conn)? ? ? 清空與這個連接對象相關(guān)的連接池很明顯,我們這次要使用ClearPool(DBConnection conn)?方法。
光說不練不驗證,不是我的風(fēng)格。
天錘壓測/queryapi 產(chǎn)生一個包含大量連接對象的連接池;適當(dāng)?shù)臅r候,調(diào)用/clearpoolapi清空連接池。
public?class?MySqlController?:?Controller??
????{??
????????//?GET:?MySql??
????????[Route("query")]??
????????public?string?Index()??
????????{??
????????????var?s?=?"User?ID=teinfra_neo_netreplay;Password=123456;DataBase=teinfra_neo_netreplay;Server=10.100.41.196;Port=3980;Min?Pool?Size=1;Max?Pool?Size=28;CharSet=utf8;";??
????????????using?(var?conn?=?new?MySqlConnection(s))??
????????????{??
????????????????var?comm?=?conn.CreateCommand();??
????????????????comm.CommandText?=?"select?count(*)?from?usertest;";??
????????????????conn.Open();??
????????????????var?ret?=?comm.ExecuteScalar();??
??
????????????????comm.CommandText?=?"select?count(*)?from?information_schema.PROCESSLIST?WHERE?HOST?like??'10.22.12.245%';";??
????????????????var?len?=?comm.ExecuteScalar();??
????????????????return?$"查詢結(jié)果:{ret}?,順便查一下當(dāng)前連接池的連接對象個數(shù):?{len}";??
????????????};??
????????}??
??
????????[Route("clearpool")]??
????????public?string?Switch()??
????????{??
????????????var?s?=?"User?ID=teinfra_neo_netreplay;Password=123456;DataBase=teinfra_neo_netreplay;Server=10.100.41.196;Port=3980;Min?Pool?Size=1;Max?Pool?Size=28;CharSet=utf8;";??
????????????using?(var?conn?=?new?MySqlConnection(s))??
????????????{??
????????????????conn.Open();??
????????????????MySqlConnection.ClearPool(conn);??
????????????};??
??
????????????using?(var?conn?=?new?MySqlConnection(s))??
????????????{??
????????????????conn.Open();??
????????????????var?comm?=?conn.CreateCommand();??
????????????????comm.CommandText?=?"select?count(*)?from?information_schema.PROCESSLIST?WHERE?HOST?like??'10.22.12.245%';";??
????????????????var?len?=?comm.ExecuteScalar();??
????????????????return?$"之前已經(jīng)清空連接池,?此次查詢連接池有?{v1}??個連接對象";??
????????????}??
??
????????}??
????}??
1、壓測產(chǎn)生大量連接對象

2、mysql數(shù)據(jù)庫對比

mysql的連接數(shù)查詢命令:?(host是web服務(wù)器IP):
select * from information_schema.PROCESSLIST WHERE HOST like '10.22.12.245%';
3、調(diào)用/clearpoolapi,清空連接池

bingo,清空連接池的理論得到驗證。
總結(jié)
這是我在同程藝龍最近爬的比較深的坑位, 在本次實踐中我們了解到:
.NET 數(shù)據(jù)庫連接池屬編程語言范疇,連接池維護(hù)了物理連接?
.NET數(shù)據(jù)庫連接池的定義方式:(同一進(jìn)程、同一連接字符串、同一連接字符串關(guān)鍵key順序一致) 被劃到一個池?
DB客戶端查詢當(dāng)前連接數(shù)的方式
根據(jù)這個思路改造祖?zhèn)鞔a,.NET數(shù)據(jù)獲取組件SDK 已經(jīng)滿足了DBA的要求。?
希望本文設(shè)計考量、理論+論證的行文思路對讀者有所幫助。
