(轉)jdbc事務隔離級別

如果DBMS支持事務處理,它必須有某種途徑來管理兩個事務同時對一個數據庫進行操作時可能發生的衝突。用戶可指定事務隔離級別,以指明DBMS應該花多大精力來解決潛在衝突。例如,當事務更改了某個值而第二個事務卻在該更改被提交或還原前讀取該值時該怎麼辦。 

  假設第一個事務被還原後,第二個事務所讀取的更改值將是無效的,那麼是否可允許這種衝突?JDBC用戶可用以下代碼來指示DBMS允許在值被提交前讀取該值("dirty讀取"),其中con是當前連接: 
con.setTransactionIsolation(TRANSACTION_READ_UNCOMMITTED); 

  事務隔離級別越高,爲避免衝突所花的精力也就越多。Connection接口定義了五級,其中最低級別指定了根本就不支持事務,而最高級別則指定當事務在對某個數據庫進行操作時,任何其它事務不得對那個事務正在讀取的數據進行任何更改。通常,隔離級別越高,應用程序執行的速度也就越慢(由於用於鎖定的資源耗費增加了,而用戶間的併發操作減少了)。在決定採用什麼隔離級別時,開發人員必須在性能需求和數據一致性需求之間進行權衡。當然,實際所能支持的級別取決於所涉及的DBMS的功能。 

  當創建Connection對象時,其事務隔離級別取決於驅動程序,但通常是所涉及的數據庫的缺省值。用戶可通過調用setIsolationLevel方法來更改事務隔離級別。新的級別將在該連接過程的剩餘時間內生效。要想只改變一個事務的事務隔離級別,必須在該事務開始前進行設置,並在該事務結束後進行復位。我們不提倡在事務的中途對事務隔離級別進行更改,因爲這將立即觸發commit方法的調用,使在此之前所作的任何更改變成永久性的。 
 

JDBC的數據隔離級別設置:
 
JDBC
數據庫隔離級別
數據訪問情況
TRANSACTION_READ_UNCOMMITTED ur 就是俗稱“髒讀”(dirty read),在沒有提交數據時能夠讀到已經更新的數據
TRANSACTION_READ_COMMITTED cs 在一個事務中進行查詢時,允許讀取提交前的數據,數據提交後,當前查詢就可以讀取到數據。update數據時候並不鎖住表
TRANSACTION_REPEATABLE_READ rs 在一個事務中進行查詢時,不允許讀取其他事務update的數據,允許讀取到其他事務提交的新增數據
TRANSACTION_SERIALIZABLE rr 在一個事務中進行查詢時,不允許任何對這個查詢表的數據修改。
 

JDBC事務隔離級別

        爲了解決與“多個線程請求相同數據”相關的問題,事務之間用鎖相互隔開。多數主流的數據庫支持不同類型的鎖;因此,JDBC API 支持不同類型的事務,它們由 Connection 對象指派或確定。在 JDBC API 中可以獲得下列事務級別:
 
TRANSACTION_NONE 說明不支持事務。

TRANSACTION_READ_UNCOMMITTED 說明在提交前一個事務可以看到另一個事務的變化。這樣髒讀、不可重複的讀和虛讀都是允許的。

TRANSACTION_READ_COMMITTED 說明讀取未提交的數據是不允許的。這個級別仍然允許不可重複的讀和虛讀產生。

TRANSACTION_REPEATABLE_READ 說明事務保證能夠再次讀取相同的數據而不會失敗,但虛讀仍然會出現。

TRANSACTION_SERIALIZABLE 是最高的事務級別,它防止髒讀、不可重複的讀和虛讀。
 
        爲了在性能與一致性之間尋求平衡纔出現了上面的幾種級別。事務保護的級別越高,性能損失就越大。
        假定您的數據庫和 JDBC 驅動程序支持這個特性,則給定一個 Connection 對象,您可以明確地設置想要的事務級別:
        conn.setTransactionLevel(TRANSACTION_SERIALIZABLE) ;
        可以通過下面的方法確定當前事務的級別:
            int level = conn.getTransactionIsolation();
            if(level == Connection.TRANSACTION_NONE)
             System.out.println("TRANSACTION_NONE");
            else if(level == Connection.TRANSACTION_READ_UNCOMMITTED)
             System.out.println("TRANSACTION_READ_UNCOMMITTED");
            else if(level == Connection.TRANSACTION_READ_COMMITTED)
             System.out.println("TRANSACTION_READ_COMMITTED");
            else if(level == Connection.TRANSACTION_REPEATABLE_READ)
             System.out.println("TRANSACTION_REPEATABLE_READ");
            else if(level == Connection.TRANSACTION_SERIALIZABLE)
             System.out.println("TRANSACTION_SERIALIZABLE");
發佈了60 篇原創文章 · 獲贊 18 · 訪問量 53萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章