數(shù)據(jù)庫(kù)連接及線程池技術(shù)原理解析._第1頁(yè)
數(shù)據(jù)庫(kù)連接及線程池技術(shù)原理解析._第2頁(yè)
數(shù)據(jù)庫(kù)連接及線程池技術(shù)原理解析._第3頁(yè)
數(shù)據(jù)庫(kù)連接及線程池技術(shù)原理解析._第4頁(yè)
數(shù)據(jù)庫(kù)連接及線程池技術(shù)原理解析._第5頁(yè)
已閱讀5頁(yè),還剩8頁(yè)未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、數(shù)據(jù)庫(kù)連接及線程池曾幾何時(shí),記住了一句話:建立數(shù)據(jù)庫(kù)連接是一個(gè)代價(jià)高昂的過(guò)程 ”,也從那時(shí)開(kāi)始,我在構(gòu)建系統(tǒng)時(shí),一旦建立起了數(shù)據(jù)庫(kù)連接,就保存起來(lái),任何要用數(shù) 據(jù)庫(kù)的地方,都使用這個(gè)數(shù)據(jù)庫(kù)連接對(duì)象進(jìn)行操作。這樣的行為,在以前寫(xiě)的單線程程序中,倒也可以接受,但在這次寫(xiě)的多線 程程序中,就出現(xiàn)問(wèn)題了。在這次的程序中,最開(kāi)始設(shè)計(jì)時(shí),在工作線程類中, 設(shè)置了一個(gè)SqlConnection 的靜態(tài)成員以接受系統(tǒng)中已經(jīng)建立起的數(shù)據(jù)庫(kù)連接對(duì) 象。大致的代碼如下:P ublic class NoPo olThreadSystem.Data.SqlClie nt.SqlC onn ectio nP ublics

2、taticDatabaseC onn ecti on = nu II;p rivate System.Threadi ng.Thread WorkThread = nu II;p rivate bool Con ti nue = false;p ublic void Start(if (WorkThread = nullThreadStart workf un = new ThreadStart(DoWork;WorkThread = new Thread(workf un;Con ti nue = true;WorkThread.Start(;p rivate void DoWork(nul

3、l;System.Diag no stics.Debug.Assert(DatabaseC onn ectio nwhile (Con ti nue/省略了使用數(shù)據(jù)庫(kù)連接對(duì)象進(jìn)行操作的代碼Thread.Slee p(300;/ end whilep ublic void Stop(if (WorkThread != nullCon ti nue = false;在主程序中,使用下面的代碼來(lái)啟動(dòng)工作線程SqlC onn ecti on conn ecti on = nu II;NoP oolThread threads = new NoP oolThread99;p rivate void bu

4、tt on 1_Click(object sen der, Eve ntArgs e conn ecti on = new SqlC onn ectio n( GetCo nn ectStri ng(;connection.Open(;NoPo olThread.DatabaseC onnection = connection;for ( int i=0; ithreadsi = new NoPo olThread(;threadsi.Start(;憑借以往的經(jīng)驗(yàn),滿心期望著:NoP oolThread 你給我好好干吧,成功就在眼前。殊不知,異常馬上就出現(xiàn),基本上是說(shuō):已有打開(kāi)的與此命令相關(guān)聯(lián)

5、的DataReader,必須首先將它關(guān)閉。ExecuteNonQuery 要求已打開(kāi)且可用的連 接。連接的當(dāng)前狀態(tài)為已關(guān)閉”。然后把threads數(shù)組長(zhǎng)度改成1,即又恢復(fù)到只有一個(gè)線程使用數(shù)據(jù)庫(kù) 連接對(duì)象時(shí),就又恢復(fù)正常。這樣就說(shuō)明了,在多個(gè)線程中使用同一個(gè)SqlConnection對(duì)象進(jìn)行數(shù)據(jù)庫(kù)操作的想法是不現(xiàn)實(shí)的也是行不通的。于是,就大著膽子,冒著巨大的代價(jià)”,進(jìn)行修改,在任何使用SqlConnection的地方,都臨時(shí)創(chuàng)建的SqlConnection對(duì)象一個(gè)對(duì)象,但是要?jiǎng)?chuàng)建對(duì)象,需要連接字符串啊,怎么來(lái)呢,不想重新寫(xiě)一遍,就用現(xiàn)成 的、已經(jīng)傳到線程對(duì)象里面的哪個(gè)數(shù)據(jù)庫(kù)連接對(duì)象里面的連接字

6、符串 吧,于是修改代碼如下:p rivate void DoWork(System.Diag no stics.Debug.Assert(DatabaseC onn ectio n != n ull;newSqlC onn ecti onconnectionSqlC onn ectio n( DatabaseC onn ectio n.C onn ectio nStri ng;while (Con ti nue使用conn ection對(duì)象Thread.Slee p(300;/ end whileconn ectio n.Close(;3.2 SqlConnection 的連接這樣修改的結(jié)果,

7、每個(gè)線程使用自己的SqlConnection對(duì)象對(duì)數(shù)據(jù)庫(kù)進(jìn)行操作,使各個(gè)線程之間互不影響。根據(jù)測(cè)試,程序可以順暢運(yùn)行,而 且在性能上沒(méi)有明顯損失,這多少有些以為,于是繼續(xù)查找資料。由于 使用的時(shí)SqlConnection對(duì)象,所以就以它為線索,首先從MSDN開(kāi)始,MSDN給出的解釋有如下內(nèi)容:SqlCo nn ection對(duì)象表示與SQL Server數(shù)據(jù)源的一個(gè)唯一的會(huì)話。 對(duì)于客戶端/服務(wù)器數(shù)據(jù)庫(kù)系統(tǒng),它等效于到服務(wù)器的網(wǎng)絡(luò)連接。SqlConnection 與 SqlDataAdapter禾0 SqlCommand 一起使用,可以在連 接Microsoft SQL Server數(shù)據(jù)庫(kù)時(shí)提高

8、性能。對(duì)于所有第三方 SQL服務(wù) 器產(chǎn)品以及其他支持 OLE DB的數(shù)據(jù)源,請(qǐng)使用 OleDbCo nn ectio n。當(dāng)創(chuàng)建SqlConnection的實(shí)例時(shí),所有屬性都設(shè)置為它們的初始 值。有關(guān)這些值的列表,請(qǐng)參見(jiàn)SqlCo nn ection構(gòu)造函數(shù)。如果SqlCo nn ection超出范圍,則不會(huì)將其關(guān)閉。因此,必須通過(guò) 調(diào)用Close或Dis pose顯式關(guān)閉該連接。它們?cè)诠δ苌鲜堑刃У?。如?將連接池值Pooling設(shè)置為true或yes,則也會(huì)釋放物理連接。還可以 打開(kāi)using塊內(nèi)部的連接,以確保當(dāng)代碼退出 usi ng塊時(shí)關(guān)閉該連接。注意:若要部署高性能應(yīng)用程序,則必須使

9、用連接池。在使用用 于SQL Server的.NET Framework數(shù)據(jù)提供程序時(shí),不必啟用連接池, 因?yàn)樘峁┏绦驎?huì)自動(dòng)對(duì)此進(jìn)行管理,不過(guò)您可以修改某些設(shè)置。從上面的解釋來(lái)看,我修改后的代碼,無(wú)意間啟用了數(shù)據(jù)庫(kù)連接池 因?yàn)槌悄阍谶B接字符串里面明確禁用連接池功能,否則默認(rèn)的數(shù)據(jù) 庫(kù)連接是從連接池中獲得連接的。3.3連接池的相關(guān)概念這里,既然提及了連接池,自己在這方面的認(rèn)識(shí)又很模糊,于是就自 己給自己了一個(gè)學(xué)習(xí)連接池的機(jī)會(huì)。連接池及ADO.NET連接到數(shù)據(jù)庫(kù)服務(wù)器通常由幾個(gè)需要很長(zhǎng)時(shí)間的步驟組成。必須建立物理通道 (例如套接字或命名管道),必須與服務(wù)器進(jìn)行初次握手,必須分析連接字符串信 息,

10、必須由服務(wù)器對(duì)連接進(jìn)行身份驗(yàn)證,必須運(yùn)行檢查以便在當(dāng)前事務(wù)中登記,等等。這就是建立數(shù)據(jù)庫(kù)連接的代價(jià),但仍然只是定性的描述。實(shí)際上,大多數(shù)應(yīng)用程序僅使用一個(gè)或幾個(gè)不同的連接配置。這意味 著在執(zhí)行應(yīng)用程序期間,許多相同的連接將反復(fù)地打開(kāi)和關(guān)閉。為了使 打開(kāi)的連接成本最低,ADO.NET使用稱為連接池的優(yōu)化方法。連接池是一種在打開(kāi)數(shù)據(jù)存儲(chǔ)區(qū)的連接時(shí)提高應(yīng)用程序性能的機(jī)制, 可以顯著提高應(yīng)用程序的性能和可縮放性。使用連接池減少新連接需要 打開(kāi)的次數(shù)。池進(jìn)程保持物理連接的所有權(quán)。通過(guò)為每個(gè)給定的連接配置保留一組活動(dòng)連接來(lái) 管理連接。只要用戶在連接上調(diào)用Open,池進(jìn)程就會(huì)檢查池中是否有可用的連接。如果某

11、個(gè)池連接可用,會(huì)將該連接返回給調(diào)用者,而不是打開(kāi)新連接。應(yīng)用程 序在該連接上調(diào)用Close時(shí),池進(jìn)程會(huì)將連接返回到活動(dòng)連接池集中,而不是真正 關(guān)閉連接。連接返回到池中之后,即可在下一個(gè)Open調(diào)用中重復(fù)使用。只有配置相同的連接可以建立池連接 。ADO.NET同時(shí)保留多個(gè)池,每個(gè)配置一個(gè) 池。連接由連接字符串以及 Windows標(biāo)識(shí)(在使用集成的安全性時(shí))分為多個(gè) 池。池連接可以大大提高應(yīng)用程序的性能和可縮放性,考慮一個(gè)訪問(wèn)SQL Server數(shù)據(jù)庫(kù)的典型ASP .NET或 WebServices應(yīng)用程序??蛻舳藨?yīng)用程序每次需要查詢數(shù)據(jù) 庫(kù)時(shí),就會(huì)在服務(wù)器端代碼中進(jìn)行往返,以打開(kāi)SqlConne

12、ction來(lái)執(zhí)行查詢。在許多此類應(yīng)用程序中,這一代碼以相同憑據(jù)一次又一次地連接到相同數(shù)據(jù)庫(kù)。理論 上,這意味著客戶端應(yīng)用程序每次需要執(zhí)行查詢時(shí),服務(wù)器端代碼需要執(zhí)行三個(gè)操 作一一登錄到數(shù)據(jù)庫(kù)(需要檢查所提供的憑據(jù)、執(zhí)行查詢、然后注銷。連接池可以 真正地提高此類應(yīng)用程序的性能 一一通過(guò)將內(nèi)部連接存儲(chǔ)在池中,并在以后進(jìn)行重 復(fù)利用,就不再因?yàn)榈卿洈?shù)據(jù)庫(kù)以及從中注銷而降低性能。對(duì)SqlConnection對(duì)象的Open和Close方法的調(diào)用可以短時(shí)間內(nèi)返回,從而可以提高代碼的性能和響應(yīng) 速度(請(qǐng)參見(jiàn)3.1圖。£.11:' '! ItSy匸圖3.1典型ASP.NET或WebS

13、ervices應(yīng)用程序中的連接池默認(rèn)情況下,ADO.NET中啟用連接池。除非顯式禁用,否則,連接在應(yīng)用程序中 打開(kāi)和關(guān)閉時(shí),池進(jìn)程將對(duì)連接進(jìn)行優(yōu)化。還可以提供幾個(gè)連接字符串修飾符來(lái)控 制連接池的行為。有關(guān)更多信息,請(qǐng)參見(jiàn) MSDN中的使用連接字符串關(guān)鍵字控制 連接池”在調(diào)用SqlConnection對(duì)象的Close方法時(shí),SQL Client .NET數(shù)據(jù)提供程序并不實(shí) 際關(guān)閉內(nèi)部連接。相反,數(shù)據(jù)提供程序?qū)⒃搩?nèi)部連接存儲(chǔ)到一個(gè)池中,以便在以后 再次使用。甚至在 SqlConnection對(duì)象被處理之后,該內(nèi)部連接也保留在池中。如果在以后使用相同連接字符串和憑據(jù)調(diào)用SqlConnection對(duì)象

14、的Open方法,將會(huì)再次使用同一內(nèi)部連接與數(shù)據(jù)庫(kù)進(jìn)行通信。Conn ection 對(duì)象的 Close 或 Dis pose 方法,因此,微軟建議在使用完連接時(shí)一定要關(guān)閉或斷開(kāi)連接,以便連接可以 返回池。要關(guān)閉連接,可以使用也可以通過(guò)在 C#的using語(yǔ)句中或在 Visual Basic的 Using語(yǔ)句中打開(kāi)所有 連接。不是顯式關(guān)閉的連接可能不會(huì)添加或返回到池中。例如,如果連 接已超出范圍但沒(méi)有顯式關(guān)閉,則僅當(dāng)達(dá)到最大池大小而該連接仍然有 效時(shí),該連接才會(huì)返回到連接池中。不是顯式關(guān)閉的連接可能無(wú)法返回 池。例如,如果連接已超出范圍但沒(méi)有顯式關(guān)閉,則僅當(dāng)達(dá)到最大池大 小而該連接仍然有效時(shí),該連

15、接才會(huì)返回到連接池中。參見(jiàn)下面的示 例。另外,如果你希望確認(rèn)是否真正再次利用了同一內(nèi)部連接,可以使用.NET Reflection中的功能以可編程方式訪問(wèn)私有 InnerConnection屬性的內(nèi) 容。以下代碼(其需要對(duì)System.Reflection命名空間的引用在Using代碼塊中 打開(kāi)一個(gè) SqlConnection,并存儲(chǔ) SqlConnection 的 InnerConnection屬性的值。通過(guò)利用Using代碼塊,在該代碼塊的末尾隱式處理了SqlConnection。此代碼在Using代碼塊中打開(kāi)另一個(gè)SqlConnection,并存儲(chǔ)SqlConnection的InnerC

16、onnection屬性的值。最后,此代碼對(duì)比InnerConnection屬性的內(nèi)容,確認(rèn)它們實(shí)際上為同一對(duì)象。stri ng strCo nn = "Data Source=.SQLEx press;l ntegrated Secunty=True;"Prop ertyI nfo propInnerConn;propInnerConn = typ eof(SqlC onn ectio n.Get Prop erty("I nn erC onn ectio n".Bindin gFlags.N onP ublic | Bindin gFlags .In

17、sta nee;object objInnerConnI, objlnnerConn2;using (SqlC onn ectio n cn = new SqlC onn ectio n(strC onncn.Open(;objInnerConnI = propinn erC onn .GetValue(c n, n ull;cn .Close(;using (SqlC onn ectio n cn = new SqlC onn ectio n(strC onncn.Open(;objlnnerConn2 = propinn erC onn .GetValue(c n, n ull;cn .C

18、lose(;Con sole.WriteL in e(obj InnerConnI = objlnnerConn2;兩個(gè)SqlConnection對(duì)象是在不同的 Using代碼塊中創(chuàng)建的,所以其資 源將在每個(gè)Using代碼塊的末尾被清除。innerConnection屬性的內(nèi)容及其 所封裝的物理連接沒(méi)有被處理,而是存儲(chǔ)在池中,以便在以后被再次利用。注意 如果在連接字符串中禁用了連接池 (稍后將解釋如何禁用,將 會(huì)看到此內(nèi)部連接不能被重復(fù)利用。連接池的創(chuàng)建和清除在初次打數(shù)據(jù)庫(kù)開(kāi)連接時(shí)例如調(diào)用SqlCo nn ectio n.Open方法時(shí),池按進(jìn)程、按應(yīng)用程序按Win dows標(biāo)識(shí)來(lái)建立進(jìn)程將根

19、據(jù)完全匹配算法創(chuàng)建連接池,該算法將池與連接中的連接字符串 關(guān)聯(lián)。每個(gè)連接池與不同的連接字符串關(guān)聯(lián)。打開(kāi)新連接時(shí),如果連接 字符串并非與現(xiàn)有池完全匹配,將創(chuàng)建一個(gè)新池。 域、按連接字符串以及(在使用集成的安全性時(shí)) 池連接。ADO.NET 2.0 引入了兩種新的方法來(lái)清除池: ClearAllPools禾0 ClearPool。 ClearAllPools清除給定提供程序的連接池, ClearPool清除與特定連接關(guān)聯(lián)的連接池。如果在調(diào)用時(shí)連接正在使用,將 進(jìn)行相應(yīng)的標(biāo)記。連接關(guān)閉時(shí),將被丟棄,而不是返回池中。連接的添加和移除連接池是為每個(gè)唯一的連接字符串創(chuàng)建的。當(dāng)創(chuàng)建一個(gè)池后,將創(chuàng)建多個(gè)連接

20、對(duì)象并將其添加到該池中,以滿足最小池大小的要求。連接根據(jù)需要添加到池中, 但是不能超過(guò)指定的最大池大小(默認(rèn)值為 100)。連接在關(guān)閉或斷開(kāi)時(shí)釋放回池 中。在請(qǐng)求SqlCo nn ection對(duì)象時(shí),如果存在可用的連接,將從池中獲取該對(duì)象。連接 要可用,必須未使用,具有匹配的事務(wù)上下文或未與任何事務(wù)上下文關(guān)聯(lián),并且具 有與服務(wù)器的有效鏈接。15秒)。如果池進(jìn)程在連接超連接池進(jìn)程通過(guò)在連接釋放回池中時(shí)重新分配連接,來(lái)滿足這些連接請(qǐng)求。如 果已達(dá)到最大池大小且不存在可用的連接,則該請(qǐng)求將會(huì)排隊(duì)。然后,池進(jìn)程嘗試 重新建立任何連接,直到到達(dá)超時(shí)時(shí)間(默認(rèn)值為 時(shí)之前無(wú)法滿足請(qǐng)求,將引發(fā)異常。Clos

21、e或Dis pose關(guān)閉的未用連連接池進(jìn)程定期掃描連接池,查找沒(méi)有通過(guò)接,并重新建立找到的連接。如果應(yīng)用程序沒(méi)有顯式關(guān)閉或斷開(kāi)其連接,連接池進(jìn) 程可能需要很長(zhǎng)時(shí)間才能重新建立連接,所以,最好確保在連接中顯式調(diào) 用 Close 和 Dispose如果連接長(zhǎng)時(shí)間空閑,或池進(jìn)程檢測(cè)到與服務(wù)器的連接已斷開(kāi),連接池進(jìn)程會(huì) 將該連接從池中移除。注意,只有在嘗試與服務(wù)器進(jìn)行通信之后才能檢測(cè)到斷開(kāi)的 連接。如果發(fā)現(xiàn)某連接不再連接到服務(wù)器,則會(huì)將其標(biāo)記為無(wú)效。無(wú)效連接只有在 關(guān)閉或重新建立后,才會(huì)從連接池中移除。如果存在與已消失的服務(wù)器的連接,那么即使連接池管理程序未檢測(cè)到已斷開(kāi) 的連接并將其標(biāo)記為無(wú)效,仍有可

22、能將此連接從池中取出。這種情況是因?yàn)闄z查連 接是否仍有效的系統(tǒng)開(kāi)銷將造成與服務(wù)器的另一次往返,從而抵消了池進(jìn)程的優(yōu) 勢(shì)。發(fā)生此情況時(shí),初次嘗試使用該連接將檢測(cè)連接是否曾斷開(kāi),并引發(fā)異常。上述連接的添加和移除,全都是由后臺(tái)運(yùn)行的池進(jìn)程管理的。禁用連接池您可能不希望使用連接池。例如,如果正在使用一個(gè)直接與數(shù)據(jù)庫(kù)進(jìn)行通信的 簡(jiǎn)單 Windows應(yīng)用程序,那么可能希望禁用連接池。在采用這一架構(gòu)時(shí),各個(gè)客 戶端應(yīng)用程序需要自己的連接。在啟用連接池時(shí),每個(gè)應(yīng)用程序的連接被放入池 中,如果在清除連接池之前重新打開(kāi)該連接,將重復(fù)利用放入池中的連接。所以, 如果應(yīng)用程序頻繁重復(fù)使用連接,那么在啟用連接池的情況下

23、,對(duì) SqlConnection.Open的調(diào)用將會(huì)更快速地返回。但是,這種方法將會(huì)導(dǎo)致在任意給 定時(shí)刻存在許多活動(dòng)的數(shù)據(jù)庫(kù)連接。禁用連接池將會(huì)降低任意時(shí)刻的活動(dòng)數(shù)據(jù)庫(kù)連 接數(shù)目,但這樣會(huì)強(qiáng)制所有對(duì) SqlCo nn ectio n.Open的調(diào)用都建立一個(gè)新的數(shù)據(jù)庫(kù)連 接。如果希望禁用連接池,可以通過(guò)向連接字符串中添加Pooling=False,逐個(gè)連接地禁用連接池。幸運(yùn)的是,在ADO.NET 2.0中不再需要記憶諸如此類的屬性。如果存在疑問(wèn),可以檢查 SqlCo nn ectio nStri ngBuilder類的選項(xiàng)。在這個(gè)類中可以找到 一個(gè)Pooling屬性,其取值為Boolean類型

24、。默認(rèn)情況下,此值被設(shè)置為 True。將 該值設(shè)置為False將會(huì)禁止將該連接放入池中。因此,在調(diào)用SqlConnection對(duì)象的Close方法時(shí),將會(huì)關(guān)閉與數(shù)據(jù)庫(kù)的實(shí)際連接。注意 在偶爾進(jìn)行連接”的Windows應(yīng)用程序中,使用連接池可能很有幫助, 具體取決于應(yīng)用程序。如果應(yīng)用程序希望定期重新連接到數(shù)據(jù)庫(kù),則可以發(fā)揮連接 池的作用,將與數(shù)據(jù)庫(kù)的物理連接保持打開(kāi)狀態(tài),至少暫時(shí)如此。如果在從池中刪 除該物理連接之前,應(yīng)用程序嘗試重新連接到該數(shù)據(jù)庫(kù),則連接池邏輯(po oli nglogic將會(huì)重新使用與該數(shù)據(jù)庫(kù)的物理連接。查看數(shù)據(jù)庫(kù)連接在使用了數(shù)據(jù)庫(kù)連接池的情況下,那么建立到數(shù)據(jù)庫(kù)上的連接到底怎么樣呢, 這可以使用 Windows的性能查看器來(lái)看

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論