1、當(dāng)處理多個訪問相同數(shù)據(jù)的用戶時,通常可能出現(xiàn)三種問題:
臟讀
當(dāng)應(yīng)用程序使用了被另一個應(yīng)用程序修改過的數(shù)據(jù),而這個數(shù)據(jù)處于未提交狀態(tài)時,就會發(fā)生臟讀。第二個應(yīng)用程序隨后會請求回滾被其修改的數(shù)據(jù)。第一個事務(wù)使用的數(shù)據(jù)就會被損壞,或者“變臟”。
不可重復(fù)的讀
當(dāng)一個事務(wù)獲得了數(shù)據(jù),而該數(shù)據(jù)隨后被一個單獨的事務(wù)所更改時,若第一個事務(wù)再次讀取更改后的數(shù)據(jù),就會發(fā)生不可重復(fù)的讀。這樣,第一個事務(wù)進行了一個不可重復(fù)的讀。
虛讀
當(dāng)事務(wù)通過某種查詢獲取了數(shù)據(jù),另一個事務(wù)修改了部分該數(shù)據(jù),原來的事務(wù)第二次獲取該數(shù)據(jù)時,就會發(fā)生虛讀。第一個事務(wù)現(xiàn)在會有不同的結(jié)果集,它可能包含虛讀。
2、Java.sql.Connection接口定義的隔離級別
TRANSACTION_NONE 說明不支持事務(wù)
TRANSACTION_READ_UNCOMMITTED 說明在提交前一個事務(wù)可以看到另一個事務(wù)的變化。這樣臟讀、不可重復(fù)的讀和虛讀都是允許的。
TRANSACTION_READ_COMMITTED 說明讀取未提交的數(shù)據(jù)是不允許的。這個級別仍然允許不可重復(fù)的讀和虛讀產(chǎn)生。
TRANSACTION_REPEATABLE_READ 說明事務(wù)保證能夠再次讀取相同的數(shù)據(jù)而不會失敗,但虛讀仍然會出現(xiàn)。
TRANSACTION_SERIALIZABLE 是最高的事務(wù)級別,它防止臟讀、不可重復(fù)的讀和虛讀。
3、事務(wù)的隔離級別
在J2EE中,通過java.sql.Connection接口設(shè)置事務(wù)隔離級別,這一接口為連接的隔離級別提供了getter()和setter()
Int getTransactionIsolation() throws SQLException
void setTransactionIsolation() throws SQLException
Connection對象負責(zé)事務(wù),一旦收到事務(wù)請求,事務(wù)將自動提交,因為Connection對象已定義為自動提交方式,可通過setAutoCommit(false)禁用自動提交模式
另外java.sql.DatabaseMetaData接口為數(shù)據(jù)存儲提供支持的隔離級別查找方法:getTransactionIsolation(),supportsTransactionIsolationLevel()
對多個庫操作的分布式事務(wù)必須在所有庫中執(zhí)行同一個隔離級別,否則會出現(xiàn)意想不到的結(jié)果
4、事務(wù)提交和回滾
為了完成提交事務(wù)和回滾事務(wù),JDBC API包括了兩個方法作為 Connection 接口的一部分。若將 Connection 對象名稱指定為 con,通過調(diào)用 con.commit(); 可以保存程序狀態(tài);
通過調(diào)用 con.rollback(); 可以返回到以前保存的狀態(tài)。如果數(shù)據(jù)庫實際運行操作時有錯誤發(fā)生,這兩個方法都會拋出 SQLExceptions,所以您需要在 try ... catch 塊中包裝它們。
5、批處理和事務(wù)
缺省情況下,JDBC 驅(qū)動程序運行在被稱為自動提交的模式下,可禁用自動提交模式
con.setAutoCommit(false);
批處理操作中通過在一次單獨的操作(或批處理)中執(zhí)行多個數(shù)據(jù)庫更新操作
{con.setAutoCommit(false) ;
Statement stmt = connection.createStatement() ; stmt.addBatch("INSERT INTO people VALUES('Joe Jackson', 0.325, 25, 105) ; stmt.addBatch("INSERT INTO people
VALUES('Jim Jackson', 0.349, 18, 99) ; stmt.addBatch("INSERT INTO people VALUES('Jack Jackson', 0.295, 15, 84) ;
int[] updateCounts = stmt.executeBatch() ; con.commit() ;