Oracle數據庫連接ResultSet_TYPE_SENSITIVE和ResultSet_TYPE_INSENSITIVE的實現原理

JDBC2.0後提出了三種不同的cursor類型,用戶代碼可以在創建Statement指定cursor類型,如下:
Statement createStatement( int resultSetType, int resultSetConcurrency)
cursor類型
ResultSet.TYPE_FORWARD_ONLY
   默認的cursor類型,僅僅支持向前forward,不支持backforward,random,last,first操作,類似單向鏈表。
   TYPE_FORWARD_ONLY類型通常是效率最高最快的cursor類型
ResultSet.TYPE_SCROLL_INSENSITIVE
   支持backforward,random,last,first操作,對其它數據session對選擇數據做出的更改是不敏感,不可見的。
ResultSet.TYPE_SCROLL_SENSITIVE
   支持backforward,random,last,first操作,對其它數據session對選擇數據做出的更改是敏感,可見的。
分析
   衆所周知,JDBC對數據庫進行數據查詢時,數據庫會創建查詢結果的cache和cursor。而數據庫的cursor是不支持backforward,random,last,first操作,僅僅只支持向前forward。那麼TYPE_SCROLL_INSENSITIVE是如何實現支持backforward,random,last,first的呢?很簡單,TYPE_SCROLL_INSENSITIVE的Statement查詢把所有fetch的記錄都緩存到JVM的Resultset對象內,如果有10個記錄,直接跳到最後記錄,TYPE_SCROLL_INSENSITIVE方式下把fetch所有記錄到jvm端,並緩存下來,再進行random就是在數據庫數組裏面進行的。這也是TYPE_FORWARD_ONLY類型通常是效率最高最快的cursor類型原因,如果要做一些複雜的功能,必然是要犧牲一些效率的。

    那麼爲什麼TYPE_SCROLL_INSENSITIVE對選擇數據做出的更改是不敏感,不可見的呢?前面提到,JDBC對數據庫進行數據查詢時,數據庫會創建查詢結果的cache和cursor,如下面sql:
    select name,id from foo
    用jdbc執行上面的sql語句時,數據庫會把foo表所有記錄的name和id字段緩存到cache中,之後cache和真正的數據庫數據文件沒有任何聯繫了,foo表發生的改變在查詢完成後不會自動同步到cache上去,因此TYPE_SCROLL_INSENSITIVE對選擇數據做出的更改是不敏感,不可見。
    那麼TYPE_SCROLL_SENSITIVE是怎麼做到其它數據session對選擇數據做出的更改是敏感,可見的。上面的sql語句用TYPE_SCROLL_SENSITIVE的Statement來執行,會轉化成以下的sql語句:
    select rowid from foo
    數據庫這時候是把foo表所有記錄的rowid緩存到cache中,用戶代碼在fetch記錄時,再繼續做以下查詢:
    select name,id from foo where rowid=?
    因此這時候發生的查詢是實時從真正的數據庫數據文件中取,因此對期間發生的數據更改是可見的,敏感的。但是這種可見性僅限於update操作,而insert和delete同樣是不可見的。因爲如果查詢發生在insert之前,insert生成的rowid並不會反應在cache中的rowid結果集上。在一個記錄的rowid已經緩存到cache中,這時候被刪除了,但一般數據庫的刪除是標記刪除,也就是說rowid對應那行記錄並沒有真正從數據庫文件中抹去,一般是可以再次取到記錄的。
總結
    TYPE_FORWARD_ONLY類型通常是效率最高最快的cursor類型,也是最常用的選擇。
    TYPE_SCROLL_INSENSITIVE需要在jvm中cache所有fetch到的記錄實體,在大量記錄集返回時慎用。
    TYPE_SCROLL_SENSITIVE在jvm中cache所有fetch到的記錄rowid,需要進行二次查詢,效率最低,開銷最大

發佈了36 篇原創文章 · 獲贊 6 · 訪問量 22萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章