關於資料庫連線池的簡單理解
資料庫連線池更多的是一個本地的概念。以前一直覺得,資料庫連線池是資料庫伺服器上的一個概念,在資料庫伺服器上有一個池,裡邊存放著很多的執行緒的資料庫連線。
最近在分析的時候,發現這是不正確的,或者說,這樣理解是不全面的。其實,連線池更多是一個執行C#程式碼的那個本地機器上的概念,當然資料庫伺服器端也有涉及,因為畢竟連線是雙方的,但是更多的這個是從連線的本地角度出發的。
下面以一個網站的例子來具體分析一下這個問題。現在有一個網站,裡邊有C#程式碼,通過程式碼訪問遠端的SQLServer資料庫,來獲取所有的銷售人員的資料。現在我們把網站部署到伺服器A上邊,資料庫存在伺服器B上邊。
假如我們不使用資料庫連線池,每次當有人開啟瀏覽器輸入網站,在
所以,這時候的思想就是,C#程式碼在本地建立了一個連線,在建立這個連線的同時,那麼我們把這個連線儲存到一個公共的區域,讓每一個
但是從資料庫伺服器的角度來講,它並不知道跟它建立連線的是一個單次的執行緒,還是資料庫連線池裡邊的連線。它只知道有個連線在跟它連著,而且在對方沒有發出斷開的請求時,它就一直連線著。(這裡可能說的不太準確,資料庫伺服器能夠知道建立的是普通連線還是連線池的連線,但是這些對於巨集觀角度來講都不重要,都是一個從遠端客戶端來的連線。)
現在的C#
當你的C#程式碼在使用類庫中的類建立連線,並且使用Open方法開啟連線的時候,這時候連線池就會初始化並建立設定的最小連線數。這時候可能就是為什麼要你安裝那個Provider,因為一個簡單的資料庫連線背後還有跟多的內容要做,可能一個dll是無法完成這個複雜的內容的。所以安裝了Provider之後,在執行C#程式碼的時候,C#程式碼引入類庫中的方法的時候,會呼叫Provider中的一些小的應用程式或者說程式集去完成複雜的內容。
最近發現Oracle資料庫的一個問題,在這篇部落格。http://blog.csdn.net/sundacheng1989/article/details/52755867
下面解釋一下原因:
說到底,每次C#程式碼new一個連線的時候(我們假設程式運行了一段時間並且連線池中有足夠的連線存在),並且Open的時候,都是去從連線池中去拿一個現成的連線。在使用完連線時一定要關閉連線,以便連線可以返回池。要關閉連線使用Close(),這時候不是真正的關閉了,還是還給了連線池。Oracle那個問題的所在就是,C#整個程式(或者也有Provider的參與)維繫著一個連線池,這個連線池中有很多的連線,在連著Oracle的資料庫伺服器。
因為很長一段時間內,Oracle資料庫伺服器那端都沒有檢測到這些連線有活動,就把這些連線給關閉了。但是應用程式維繫的連線池並沒有覺察到,所以一天後當再次new一個連線,conn.Open的時候,應用程式還是從連線池中拿了一個,並不知道拿的這個已經關閉了,C#程式碼繼續進行著進一步的查詢操作,這時候發現連不上了,所以,就丟擲了這個異常。這時候可以通過禁用連線池來解決這個問題,但是效能上就不太好了。
在主流的C#或者Java中,你生成一個連線的時候,預設的都是用連線池維護的,除非你明確指明瞭不使用連線池(在配置檔案的連線字串中加入threadingPool=false),這時候才會是每一個執行緒都建立一個連線並且完事後銷燬這個連線。