如果DBMS支持事務處理,它必須有某種途徑來管理兩個事務同時對一個數據庫進行操作時可能發生的衝突。用戶可指定事務隔離級別,以指明DBMS應該花多大精力來解決潛在衝突。例如,當事務更改了某個值而第二個事務卻在該更改被提交或還原前讀取該值時該怎麼辦。
假設第一個事務被還原後,第二個事務所讀取的更改值將是無效的,那麼是否可允許這種衝突?JDBC用戶可用以下代碼來指示DBMS允許在值被提交前讀取該值("dirty讀取"),其中con是當前連接:
con.setTransactionIsolation(TRANSACTION_READ_UNCOMMITTED);
事務隔離級別越高,爲避免衝突所花的精力也就越多。Connection接口定義了五級,其中最低級別指定了根本就不支持事務,而最高級別則指定當事務在對某個數據庫進行操作時,任何其它事務不得對那個事務正在讀取的數據進行任何更改。通常,隔離級別越高,應用程序執行的速度也就越慢(由於用於鎖定的資源耗費增加了,而用戶間的併發操作減少了)。在決定採用什麼隔離級別時,開發人員必須在性能需求和數據一致性需求之間進行權衡。當然,實際所能支持的級別取決於所涉及的DBMS的功能。
當創建Connection對象時,其事務隔離級別取決於驅動程序,但通常是所涉及的數據庫的缺省值。用戶可通過調用setIsolationLevel方法來更改事務隔離級別。新的級別將在該連接過程的剩餘時間內生效。要想只改變一個事務的事務隔離級別,必須在該事務開始前進行設置,並在該事務結束後進行復位。我們不提倡在事務的中途對事務隔離級別進行更改,因爲這將立即觸發commit方法的調用,使在此之前所作的任何更改變成永久性的。
JDBC
|
數據庫隔離級別
|
數據訪問情況
|
TRANSACTION_READ_UNCOMMITTED | ur | 就是俗稱“髒讀”(dirty read),在沒有提交數據時能夠讀到已經更新的數據 |
TRANSACTION_READ_COMMITTED | cs | 在一個事務中進行查詢時,允許讀取提交前的數據,數據提交後,當前查詢就可以讀取到數據。update數據時候並不鎖住表 |
TRANSACTION_REPEATABLE_READ | rs | 在一個事務中進行查詢時,不允許讀取其他事務update的數據,允許讀取到其他事務提交的新增數據 |
TRANSACTION_SERIALIZABLE | rr | 在一個事務中進行查詢時,不允許任何對這個查詢表的數據修改。 |
JDBC事務隔離級別
TRANSACTION_READ_UNCOMMITTED 說明在提交前一個事務可以看到另一個事務的變化。這樣髒讀、不可重複的讀和虛讀都是允許的。
TRANSACTION_READ_COMMITTED 說明讀取未提交的數據是不允許的。這個級別仍然允許不可重複的讀和虛讀產生。
TRANSACTION_REPEATABLE_READ 說明事務保證能夠再次讀取相同的數據而不會失敗,但虛讀仍然會出現。
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");