Java原理 事務的ACID是指什麼? 1、什麼是Java事務 一般的觀念認爲,事務僅與數據庫相關。 事務必須服從ISO/IEC所制定的ACID原則。 ACID是原子性(atomicity)、一致性(consistency)、隔離性 (isolation)和持久性(durability)的縮寫。java
原子性表示事務執行過程當中的任何失敗都將致使事務所作的任何修改失效。
一致性表示當事務執行失敗時,全部被該事務影響的數據都應該恢復到事務執行前的狀態。程序員
隔離性表示在事務執行過程當中對數據的修改,在事務提交以前對其餘事務不可見。sql
持久性表示已提交的數據在事務執行失敗時,數據的狀態都應該正確。數據庫
通俗的理解,事務是一組原子操做單元,從數據庫角度說,就是一組SQL指令,要麼所有執行成功,若由於某個緣由其中一條指令執行有錯誤,則撤銷先前執行過的全部指令。更簡單的說就是:要麼所有執行成功,要麼撤銷不執行。安全
既然事務的概念從數據庫而來,那Java事務是什麼?之間有什麼聯繫?服務器
實際上,一個Java應用系統,若是要操做數據庫,則經過JDBC來實現的。增長、修改、刪除都是經過相應方法間接來實現的,事務的控制也相應轉移到Java程序代碼中。所以,數據庫操做的事務習慣上就稱爲Java事務。網絡
2、爲何須要事務 事務是爲解決數據安全操做提出的,事務控制實際上就是控制數據的安全訪問。併發
舉一個簡單例子:好比銀行轉賬業務,帳戶A要將本身帳戶上的1000元 轉到B帳戶下面,A帳戶餘額首先要減去1000元,而後B帳戶要增長1000元。假如在中間網絡出現了問題,A帳戶減去1000元已經結束,B由於網絡中斷而操做失敗,那麼整個業務失敗,必須作出控制,要求A帳戶轉賬業務撤銷。這才能保證業務的正確性,完成這個操走就須要事務,將A帳戶資金減小和B帳戶資金增長方到一個事務裏面,要麼所有執行成功,要麼操做所有撤銷,這樣就保持了數據的安全性。分佈式
3、Java事務的類型 Java事務的類型有三種:JDBC事務、JTA(Java Transaction API)事務、容器事務。 一、JDBC事務 JDBC 事務是用 Connection 對象控制的。JDBC Connection 接口( java.sql.Connection )提供了兩種事務模式:自動提交和手工提交。高併發
java.sql.Connection 提供瞭如下控制事務的方法:
public void setAutoCommit(boolean) public boolean getAutoCommit() public void commit() public void rollback() 使用 JDBC 事務界定時,您能夠將多個 SQL 語句結合到一個事務中。
JDBC 事務的一個缺點是事務的範圍侷限於一個數據庫鏈接。一個 JDBC 事務不能跨越多個數據庫。
二、JTA(Java Transaction API)事務 JTA是一種高層的,與實現無關的,與協議無關的API,應用程序和應用服務器可使用JTA來訪問事務。 JTA容許應用程序執行分佈式事務處理–在兩個或多個網絡計算機資源上訪問而且更新數據,這些數據能夠分佈在多個數據庫上。
JDBC驅動程序的JTA支持極大地加強了數據訪問能力。
若是計劃用 JTA 界定事務,那麼就須要有一個實現 javax.sql.XADataSource 、 javax.sql.XAConnection 和 javax.sql.XAResource 接口的 JDBC 驅動程序。一個實現了這些接口的驅動程序將能夠參與 JTA 事務。
一個 XADataSource 對象就是一個 XAConnection 對象的工廠。 XAConnection s 是參與 JTA 事務的 JDBC 鏈接。
您將須要用應用服務器的管理工具設置 XADataSource 。從應用服務器和 JDBC 驅動程序的文檔中能夠了解到相關的指導。 J2EE 應用程序用 JNDI 查詢數據源。一旦應用程序找到了數據源對象,它就調用 javax.sql.DataSource.getConnection() 以得到到數據庫的鏈接。 XA 鏈接與非 XA 鏈接不一樣。必定要記住 XA 鏈接參與了 JTA 事務。這意味着 XA 鏈接不支持 JDBC 的自動提交功能。
同時,應用程序必定不要對 XA 鏈接調用 java.sql.Connection.commit() 或者 java.sql.Connection.rollback() 。
相反,應用程序應該使用 UserTransaction.begin()、 UserTransaction.commit() 和 serTransaction.rollback() 。
三、容器事務 容器事務主要是J2EE應用服務器提供的,容器事務大可能是基於JTA完成,這是一個基於JNDI的,至關複雜的API實現。相對編碼實現JTA事 務管理,咱們能夠經過EJB容器提供的容器事務管理機制(CMT)完成同一個功能,這項功能由J2EE應用服務器提供。
這使得咱們能夠簡單的指定將哪一個方法加入事務,一旦指定,容器將負責事務管理任務。這是咱們土建的解決方式,由於經過這種方式咱們能夠將事務代碼排除在邏輯編碼以外,同時將全部困難交給J2EE容器去解決。
使用EJB CMT的另一個好處就是程序員無需關心JTA API的編碼,不過,理論上咱們必須使用EJB。
4、三種事務差別 一、JDBC事務控制的侷限性在一個數據庫鏈接內,可是其使用簡單。 二、JTA事務的功能強大,事務能夠跨越多個數據庫或多個DAO,使用也比較複雜。 三、容器事務,主要指的是J2EE應用服務器提供的事務管理,侷限於EJB應用使用。
5、總結 事務控制是構建J2EE應用不可缺乏的一部分,合理選擇應用何種事務對整個應用系統來講相當重要。通常說來,在單個JDBC 鏈接鏈接的狀況下能夠選擇JDBC事務,在跨多個鏈接或者數據庫狀況下,須要選擇使用JTA事務,若是用到了EJB,則能夠考慮使用EJB容器事務。
拓展:
關於事務,首先須要知道的是,只有存在併發數據訪問時才須要事務。
當多個事務訪問同一數據時,可能會存在5類問題,包括3類數據讀取問題(髒讀、不可重複讀和幻讀)和2類數據更新問題(第1類丟失更新和第2類丟失更新)。
髒讀(Dirty Read):A事務讀取B事務還沒有提交的數據並在此基礎上操做,而B事務執行回滾,那麼A讀取到的數據就是髒數據。
時間
轉帳事務A
取款事務B
T1
開始事務
T2
開始事務
T3
查詢帳戶餘額爲1000元
T4
取出500元餘額修改成500元
T5
查詢帳戶餘額爲500元(髒讀)
T6
撤銷事務餘額恢復爲1000元
T7
匯入100元把餘額修改成600元
T8
提交事務
不可重複讀(Unrepeatable Read):事務A從新讀取前面讀取過的數據,發現該數據已經被另外一個已提交的事務B修改過了。
時間
轉帳事務A
取款事務B
T1
開始事務
T2
開始事務
T3
查詢帳戶餘額爲1000元
T4
查詢帳戶餘額爲1000元
T5
取出100元修改餘額爲900元
T6
提交事務
T7
查詢帳戶餘額爲900元(不可重複讀)
幻讀(Phantom Read):事務A從新執行一個查詢,返回一系列符合查詢條件的行,發現其中插入了被事務B提交的行。
時間
統計金額事務A
轉帳事務B
T1
開始事務
T2
開始事務
T3
統計總存款爲10000元
T4
新增一個存款帳戶存入100元
T5
提交事務
T6
再次統計總存款爲10100元(幻讀)
第1類丟失更新:事務A撤銷時,把已經提交的事務B的更新數據覆蓋了。
時間
取款事務A
轉帳事務B
T1
開始事務
T2
開始事務
T3
查詢帳戶餘額爲1000元
T4
查詢帳戶餘額爲1000元
T5
匯入100元修改餘額爲1100元
T6
提交事務
T7
取出100元將餘額修改成900元
T8
撤銷事務
T9
餘額恢復爲1000元(丟失更新)
第2類丟失更新:事務A覆蓋事務B已經提交的數據,形成事務B所作的操做丟失。
時間
轉帳事務A
取款事務B
T1
開始事務
T2
開始事務
T3
查詢帳戶餘額爲1000元
T4
查詢帳戶餘額爲1000元
T5
取出100元將餘額修改成900元
T6
提交事務
T7
匯入100元將餘額修改成1100元
T8
提交事務
T9
查詢帳戶餘額爲1100元(丟失更新)
數據併發訪問所產生的問題,在有些場景下多是容許的,可是有些場景下可能就是致命的,數據庫一般會經過鎖機制來解決數據併發訪問問題,按鎖定對象不一樣能夠分爲表級鎖和行級鎖;按併發事務鎖定關係能夠分爲共享鎖和獨佔鎖,具體的內容你們能夠自行查閱資料進行了解。 直接使用鎖是很是麻煩的,爲此數據庫爲用戶提供了自動鎖機制,只要用戶指定會話的事務隔離級別,數據庫就會經過分析SQL語句而後爲事務訪問的資源加上合適的鎖,此外,數據庫還會維護這些鎖經過各類手段提升系統的性能,這些對用戶來講都是透明的(就是說你不用理解,事實上我確實也不知道)。
ANSI/ISO SQL 92標準定義了4個等級的事務隔離級別,以下表所示:
隔離級別
髒讀
不可重複讀
幻讀
第一類丟失更新
第二類丟失更新
READ UNCOMMITED
容許
容許
容許
不容許
容許
READ COMMITTED
不容許
容許
容許
不容許
容許
REPEATABLE READ
不容許
不容許
容許
不容許
不容許
SERIALIZABLE
不容許
不容許
不容許
不容許
不容許
須要說明的是,事務隔離級別和數據訪問的併發性是對立的,事務隔離級別越高併發性就越差。
因此要根據具體的應用來肯定合適的事務隔離級別,這個地方沒有萬能的原則。