什麼是數據庫事務
事務:一組邏輯操作單元,使數據從一種狀態轉換到另一種狀態
事務處理保證所有的事務都作爲一個工作單元執行,即使出現了故障,都不能改變這種執行方式,當在一個事務中執行多個操作時,要麼所有的事務都被提交,那麼這些操作就 永遠的保存下來,要麼數據庫系統放棄所做的所有修改,將整個事務回滾到最初的狀態
爲確保數據庫中數據的一致性,數據的操縱應該是離散的成組的邏輯單元,當它全部完成時,數據的一致性可以保持,而當這個單元中的一部分操作失敗,整個事務全部被歸爲錯誤操作,所有從最初開始的操作全部回退到最初的開始狀態
JDBC事務處理
1.數據庫一旦提交就不可以回滾
2.如何判斷數據庫已經提交
當一個連接對象被創建時,默認情況下是自動提交事務,每次執行一條sql語句時,如果執行成功,則向數據庫自動提交,而不能回滾
關閉數據庫連接,數據就會自動的提交,如果有多個操作,每個操作使用的是自己單獨的連接,則無法保證事務,即同一個事務的多個操作必須在同一個連接下
處理方法
調用Connection對象中的setAutoCommit(false),取消事務的自動提交,在所有sql語句執行完之後調用對象中的commit();提交事務在出現異常時在處理異常的方法調用rollBack();方法,使事務回滾但最初狀態
注意
如果Connection沒有被關閉,還可能會被重複使用,則需要恢復自動提交狀態調用setAutoCommit(true);在使用數據庫連接池技術是,執行close()方法前建議恢復自動提交狀態
@Test
public void testUpdate(){
Connection conn = null;
try {
conn = JDBCUtils.getConnection();
//取消數據的自動提交
conn.setAutoCommit(false);
String sql1 = "update user_table set balance = balance - 100 where user = ?";
update(conn,sql1,"AA");
//異常
System.out.println(100 / 0);
String sql2 = "update user_table set balance = balance + 100 where user = ?";
update(conn,sql2,"BB");
//提交數據
conn.commit();
} catch (Exception e){
e.printStackTrace();
//回滾數據
try {
conn.rollback();
} catch (SQLException ex) {
ex.printStackTrace();
}
} finally {
try {
conn.setAutoCommit(true);
} catch (SQLException e) {
e.printStackTrace();
}
JDBCUtils.closeResource(conn,null);
}
}
//考慮數據庫事務
public void update(Connection conn,String sql,Object ...args) {
//獲取數據庫連接
PreparedStatement ps = null;
try {
conn = JDBCUtils.getConnection();
//預編譯sql語句返回PreparedStatement的實例
ps = conn.prepareStatement(sql);
//填充佔位符
for(int i = 0; i < args.length; i++){
ps.setObject(i+1,args[i] );
}
//執行
ps.execute();
}catch (Exception e){
e.printStackTrace();
}finally {
JDBCUtils.closeResource(null,ps);
}
//關閉資源
}
表數據
事務的ACID屬性
1原子性(Atomicity)
原子性是指事務是一個不可分割的工作單位,事務中的操作要麼都發生,要麼都不發生。
2一致性(Consistency)
事務必須是數據庫從一個一致性狀態變換到另外一個一致性狀態
3隔離性(Isolation)
事務的隔離性是指一個事務的執行不能被其他事務干擾,即事務內部的操作和使用的數據庫不受其他影響
4持久性(Durability)
事務的持久性是指一個事務一旦被提交,則對數據庫中的數據的改變將是永久性的,接下來的其他操作和故障將不會對其有任何影響
數據操作過程中可能出現的問題(針對隔離性)
對於同時運行多個事務時,當這些事務訪問數據庫中相同的數據時,如果沒有采取必要的隔離機制,就會導致各種併發問題
髒讀:對於兩個事務t1和t2,t1讀取了以被t2更新但沒有提交的字段,在此之後如果t2回滾,t1讀取的內容就是臨時且無效的
不可重複讀:對於兩個事務t1和t2,t1讀取了一個字段,之後t2更新了該字段,之後t1再次讀取該字段,值也會改變
幻讀:對於兩個事務t1和t2,t1從一個表中讀取了一個字段,然後t2在該表中插入了一些新的行,之後t1在此讀取則會多出現幾行
數據庫的四種隔離級別:(一致性和併發性:一致性越好,併發性越差)
Oracle支持兩種事務隔離級別:READ COMMITED,SERIALIZABLE 默認爲第一種
Mysql支持4種隔離級別,默認的隔離級別爲:REPEATABLE READ
#查看當前的隔離級別
select @@tx_isolation;
設置mysql連接的隔離級別
set transaction isolation level read committed;
#設置數據庫系統的全局隔離級別
set global transaction isolation level read committed;