學習數據庫事務


學習數據庫事務

什么是事務

事務(Transaction)是並發控制的基本單位。所謂的事務,它的根本是一個操作序列,這些操作都執行,或者都不執行,它是一個無法分割的工作單位。

例如銀行轉賬:從一個賬戶扣款並使另一個賬戶贈款,這兩個操作要么都執行,要么都不執行,不能存在執行一半,否則會出現金額消失或者無中生有。所以我們能夠把整個操作的過程,看成一個事務。

事務是數據庫維護數據一致性的單位,在威哥事務結束時,都能保持數據一致性。事務具有四個基本特征:Atomic(原子性),Consistency(一致性),Isolation(隔離性),Durability(持久性),簡稱ACID。

  • 原子性:表示組成一個事務的多個數據庫操作是一個不可分割的原子單元,只有所有的操作執行成功,整個事務才能提交,事務中任何一個數據操作失敗,已經執行的任何操作都必須撤銷,讓數據庫返回到初始狀態。
  • 一致性:實務操作成功后,數據庫所處的狀態和他的業務規則是一致的,即數據不會被破壞。
  • 隔離性:在並發數據操作時,不同的事務擁有各自的數據空間,他們的操作不會對對方產生干擾。
  • 持久性:一旦事務提交成功后,事務中所有的數據操作都必須被持久化到數據庫中,及時事務提交之后,數據庫馬上崩潰,在數據庫重啟之后能夠通過某種及時回復數據。

數據一致性是最終目標,其他的特性都是為了達到這個目標的措施、要求或手段。

數據庫管理系統一般采用重執行日志保證原子性、一致性和持久性,重執行日志記錄了數據庫變化的每一個動作,數據庫在一個事務中執行一部分操作后發生錯誤退出,數據庫即可以根據重執行日志撤銷已經執行的操作。對於已經提交的事務,即使數據庫崩潰,在重啟數據庫時也能夠根據日志對尚未持久化的數據進行相應的重執行操作。

數據庫鎖機制

  • 數據庫通過鎖的機制解決並發訪問問題。
  • 按鎖定的對象不同,一般可以分為表鎖定和行鎖定,前者對整個表鎖定,后者對表中特定行進行鎖定。InnoDB具有行鎖定機制。
  1. 共享鎖【S鎖】
    又稱讀鎖,若事務T對數據對象A加上S鎖,則事務T可以讀A但不能修改A,其他事務只能對A加S鎖,而不能加X鎖。指導T釋放A上的S鎖。這保證了其他事務可以讀A,但在T釋放A上的鎖之前不能對A做任何操作。
  2. 獨占鎖或排他鎖【X鎖】
    又稱寫鎖,若事務T對數據對象A加上X鎖,則事務T可以讀A也可以修改A,其他事物不能夠在對A加任何鎖,直到T釋放A上的鎖。這保證了其他事務在T釋放A上的所之前不能夠再讀取和修改A。

事務隔離級別

ANSI/ISO SQL 92標准定義了4個等級的事務隔離級別。不同的事務隔離級別能夠解決的數據並發問題的能力是不同的。

  • Read UnCommitted(未提交讀):事務中的修改,及時沒有提交,對其他事務也都是可見的。事務可以讀取未提交的數據,這也被稱為臟讀(Dirty Read),使用這個級別的數據庫擁有最高的並發和吞吐量。在實際中很少使用。
  • Read Committed(提交讀):大多數數據庫的默認隔離級別都是這個(但是Mysql不是)。這個級別蠻熟隔離性的定義:一個事務開始是,只能“看見”已經提交的事務所做的修改。一個事務從開始指導提交之前,所做的任何修改操作對其他事務都是不可見的 。這個幾倍優勢后也叫作不可重復讀(Nonrepeatable Read),因為兩次執行同樣的執行可能得到不一樣的結果。
  • Repeatable Read(可重復讀):該級別結局了臟讀的問題。該級別保證了在一個事務中多次讀取同樣的記錄的結果是一致的。但還是沒有解決幻讀(Phantom Read)的問題。所謂幻讀:值得是當某個事務在讀取某個范圍的記錄是,另一個事務又在該范圍內插入了新的記錄,當之前事務再次讀取該范圍的記錄時,會產生幻行(Phantom Row)。不過Mysql的InnoDB存儲引擎通過多版本並發控制(MVCC)解決幻讀的問題。該級別是Mysql的默認事務隔離級別。
  • Serializable(可串行化):該級別是最高的隔離級別。他通過強制事務串行執行,避免了前面的幻讀問題。該級別都會在讀取的每一行數據都加上鎖,所以可能導致大量的超時和鎖競爭的問題。實際應用中很好使用這個隔離級別,只要在非常需要確保數據的只執行而且可以接受沒有並發情況下,才會考慮采用該級別。

Java事務的類型

Java事務的類型有三種:JDBC事務、JTA(Java Transaction API)事務、容器事務。

  1. 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事務不能跨越多個數據庫。

  1. JTA(Java Transation API)事務

JTA是一種高層的,已實現無關的,與協議無關的API,應用程序和應用服務器可以使用JTA來訪問事務。
JTA允許用用程序執行分布式處理——在一個或多個網絡計算機資源訪問並且更新數據,這些數據可以分布在多個數據庫上。JDBC驅動程序的JTA支持極大的增強數據訪問能力。
如果使用JTA界定事務,那么就需要實現javax.sql.XADataSoure、javax.sql.XAConnection和java.sqlXAResource接口的JDBC驅動程序。一個實現了這些接口的驅動程序將可以參與到JTA事務。一個XADataSource對象就是一個XAConnection對象的工廠。XAConnection是參與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()和UserTransaction.rollback()。

  1. 容器事務

容器事務主要是J2EE應用服務器提供的,容器事務大多是基於JTA完成,這是一個基於JNDI的,相當復雜的API實現。相對編碼實現JTA事務管理, 我們可以通過EJB容器提供的容器事務管理機制(CMT)完成同一個功能,這項功能由J2EE應用服務器提供。這使得我們可以簡單的指定將哪個方法加入事 務,一旦指定,容器將負責事務管理任務。這是我們土建的解決方式,因為通過這種方式我們可以將事務代碼排除在邏輯編碼之外,同時將所有困難交給J2EE容 器去解決。使用EJB CMT的另外一個好處就是程序員無需關心JTA API的編碼,不過,理論上我們必須使用EJB.

三種Java事務差異

  1. JDBC事務控制的局限性在一個數據庫連接內,但是其使用簡單。
  2. JTA事務的功能強大,事務可以跨越多個數據庫或多個DAO,使用也比較復雜。
  3. 容器事務,主要指的是J2EE應用服務器提供的事務管理,局限於EJB應用使用。

總結

Java事務控制是構建J2EE應用不可缺少的一部分,合理選擇應用何種事務對整個應用系統來說至關重要。一般說來,在單個JDBC 連接連接的情況下可以選擇JDBC事務,在跨多個連接或者數據庫情況下,需要選擇使用JTA事務

Code

Connection conn ;
try {
		//    獲取數據連接
       	conn = DriverManager.getConnection();
       	// 關閉自動提交的機制
       	conn.setAutoCommit(false);    
       	// 設置事務隔離級別    
      	conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
       	Statement stmt = conn.createStatement(); 
       	int rows = stmt.executeUpdate("INSERT INTO t_topic VALUES(1,'tom')");
       	rows = stmt.executeUpdate("UPDATE t_user set topic_nums=topic_nums+1 WHERE user_id=1");
       	conn.commit();         // 提交事務
    }catch(Exception e) {
    	conn.rollback();    // 回滾事務
    }finally {
      ...
    }
}	


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM