DataReader不奇怪,该出手时就出手!
夜里三點多,剛完成微博粉絲精靈V3.763的微博升級,上來看看,剛看到一篇文章:【原】關(guān)于使用DataReader的一個很奇怪的問題,不應該用DataReader?
于是準備花點時間解答下,順便為這個月增添一篇文章。
?
關(guān)于DataReader,以前寫過一篇文章,可參考:DataReader?鏈接關(guān)閉解惑篇?
?
下面將對原文,解答兩個問題:
?
一:?DataReader、DataTable、DataSet 的簡單關(guān)系:
?
這里先取原文的第一句話:.net讀取數(shù)據(jù)集有兩種方式:DataSet?和?DataReader
解答:.net 的Command操作里,默認可以有三種返回:DataReader、DataTable、DataSet
?
這三者的簡單關(guān)系為:
?
DataReader?快速只向前讀的流,需要開發(fā)者自己去關(guān)閉流。DataTable?一個容器,把DataReeader讀到DataTable容器后關(guān)閉流。
DataSet 一個大容器,里面可放置多個DataTable。
因此開發(fā)者,首先要明白這三者的簡單關(guān)系,才不至于亂猜。
?
二:數(shù)據(jù)庫鏈接、鏈接池、close與dispose
?
這里再取原文的第N句話:在sqlserver(2000)中查看進程,有非常多的sleeping進程,直到最后打開頁面,提示超時,說連接池滿。
?
解答:默認mssql的鏈接數(shù)是有限的,大體在100多個,簡單的說你可以open 100多次而不關(guān)閉,超過后再open就會出現(xiàn)鏈接池不夠的現(xiàn)象。
這之間的簡單關(guān)系為:
?
第一次Open出鏈接時,連接數(shù)據(jù)庫(由于是首次建立鏈接,需要初始化先多信息,就是傳說的性能問題)然后你Close時,數(shù)據(jù)庫斷開鏈接,同時把鏈接狀態(tài)改成sleep,但是不銷毀(為了下次建立鏈接時省掉初始化,避免傳說中的性能問題),這個不銷毀的鏈接,放到一個池里面,被稱之為鏈接池。
如果你Dispose(),則會把鏈接從池里銷毀,當然下次鏈接就會開始新的初始化。
?
下面就會有很多種情況出現(xiàn):
?
情況一:一個線程的正常操作:
?
如果使用時一個流程下來,是按順序的open->close-open->close 狀態(tài),那么始終只用到一個鏈接(從連接池里進進出出),基本沒有過多的初始化問題,傳說性能好。
?
情況二:多個線程的不正常操作:
?
如果你一個鏈接,在Open狀態(tài),這時候另一個線程也要打開鏈接,發(fā)現(xiàn)鏈接池沒有時,就會重新到數(shù)據(jù)庫建一個鏈接(又開始初始化,一堆信息,最后產(chǎn)生一個鏈接)。
如果你所有的鏈接全在Open,不關(guān)閉,或者時間拖的很多,在其它線程要鏈接的時候,你的鏈接還沒關(guān)閉,在產(chǎn)生100多個鏈接后,數(shù)據(jù)庫最大數(shù)滿了,就會出現(xiàn)“鏈接池已滿”的情況。?
?
情況三:多個線程的正常操作:
?
如果你懂的每個鏈接打開后,都快速關(guān)閉,通常一個正常語句的操作時間在0.001-0.1秒左右,這樣關(guān)閉的鏈接就回到池里,可以快速供給其它線程使用。
這樣,僅需要幾十個鏈接,就可以循環(huán)的使用處理多線程問題。?
?
簡單的假設(shè):
如果一個操作open到close,用時0.1秒一次, 那么一個鏈接在1秒內(nèi)可以處理10次操作。而100個鏈接最大數(shù)就可以支持1000次操作。
簡單的說就是1秒可以并發(fā)操作1000次以上,這對中小網(wǎng)站來說,處理是相當容易的事。
而新手容易犯的錯誤,就是鏈接打開后,長時間的不關(guān)閉,最后導致在多線程的情況下,把數(shù)據(jù)庫鏈接資源用盡了,出現(xiàn)了錯誤而不得知。?
?
進一步的假設(shè):
在很多的程序處理中,對數(shù)據(jù)庫的操作時間,往往是不平均的,這就需要有點經(jīng)驗的程序開發(fā)者,花點時間,來搞好這最大并發(fā)問題,通常是:
對長時間查詢的,使用緩存(避免二次查詢),或者集中使用隊列(因為使用隊列,就一個鏈接就可以搞定了,反正是開了讀和關(guān),然后下一個又是開了讀和關(guān),始終是一個鏈接),當然使用隊列也要看情況。
對于時間短的,直接處理就可以了。
?
其實說白了,越往上,就越是“看情況處理”,沒有啥定律,要是有,那就是數(shù)據(jù)庫的最大鏈接數(shù),無論你怎么耍流氓,反正你不能讓它一次性給用完。?
?
補充點:
在sqlserver(2000)中查看進程,有非常多的sleeping進程,直到最后打開頁面,提示超時,說連接池滿,為什么,既然已經(jīng)了很多 sleeping 的數(shù)據(jù)庫連接, 為什么還會出現(xiàn) 不能連接數(shù)據(jù)庫 的問題呢???
答:
對于ADO.NET,它有一種機制,來分析是使用產(chǎn)生新的會話還是直接從鏈接池中返回,例如,不同的數(shù)據(jù)庫鏈接,它會產(chǎn)生新的鏈接,而不會從原有鏈接池里返回。而對于mssql,可能某種檢測機制原因(不同的線程或進程鏈接),mssql分析后直接是為你產(chǎn)生新的鏈接,而不是從sleep狀態(tài)的鏈接池返回,因此,原來的sleep無法復用,再次產(chǎn)生新的鏈接,就報鏈接池滿了。
轉(zhuǎn)載于:https://www.cnblogs.com/cyq1162/archive/2012/04/21/2460964.html
總結(jié)
以上是生活随笔為你收集整理的DataReader不奇怪,该出手时就出手!的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java: IE Firefox下载文
- 下一篇: UDP协议下数据的传输分析