JAVA事務系列三:JTA事務

什麼是JTA?

JTA全稱Java Transaction API ,即Java事務API,英文解釋:

Java Transaction API (JTA) specifies standard Java interfaces between a transaction manager and the parties involved in a distributed transaction system: the resource manager, the application server, and the transactional applications.java

JTA是一種高層的,與實現無關的,與協議無關的API,應用程序和應用服務器可使用JTA來訪問事務。 sql

JTA容許應用程序執行分佈式事務處理--在兩個或多個網絡計算機資源上訪問而且更新數據,這些數據能夠分佈在多個數據庫上。JDBC驅動程序的JTA支持極大地加強了數據訪問能力。 數據庫

JTA的主要接口:

位於javax.transaction包中編程

a、UserTransaction接口:讓應用程序得以控制事務的開始、掛起、提交、回滾等。由Java客戶端程序或EJB調用。
b、TransactionManager 接口:用於應用服務器管理事務狀態
c、Transaction接口:用於執行相關事務操做
d、XAResource接口:用於在分佈式事務環境下,協調事務管理器和資源管理器的工做
e、Xid接口:爲事務標識符的Java映射服務器

注:前3個接口位於Java EE版的類庫 javaee.jar 中,Java SE中沒有提供!UserTransaction是編程經常使用的接口。JTA只提供了接口,沒有具體的實現。網絡

JTA須要知足的條件:

若是使用 JTA 界定事務,那麼就須要有一個實現 javax.sql.XADataSource 、 javax.sql.XAConnection 和 javax.sql.XAResource 接口的 JDBC 驅動程序。一個實現了這些接口的驅動程序才能夠參與 JTA 事務。 架構

一個 XADataSource 對象就是一個 XAConnection 對象的工廠。 XAConnection 是參與 JTA 事務的 JDBC 鏈接。要使用JTA事務,必須使用XADataSource來產生數據庫鏈接,產生的鏈接爲一個XA鏈接。 app

XA鏈接(javax.sql.XAConnection)和非XA(java.sql.Connection)鏈接的區別在於: nosql

XA能夠參與JTA的事務,並且不支持像JDBC那樣的自動提交分佈式

同時,應用程序必定不要對 XA 鏈接調用 java.sql.Connection.commit() 或者 java.sql.Connection.rollback() 。相反,應用程序應該使用 UserTransaction.begin()、 UserTransaction.commit() 和 serTransaction.rollback() 。

注意: Oracle, Sybase, DB2, SQL Server等大型數據庫才支持XA, 支持分佈事務。 MySQL屬於Non-XA。

事務管理器模型(TM):

Java Transaction API 容許您操做應用程序中的分佈式事務(Distributed Transaction)。JTA 中有一組方法,它將傳統的 JDBC 調用封裝到了兩階段提交(Two-Phase-Commit)協議中。

在異構環境中,您一般會發現一個事務管理器(Transaction Manager),負責處理分佈式事務。(實際上,事務管理器能夠完成大量的工做負載平衡。)所以,不只存在到數據庫的直接鏈接,還有到事務管理器 (Transaction Manager)的鏈接。這就是 JTA 發揮做用的地方:JTA 是 Java 應用程序和事務管理器(Transaction Manager)之間的接口。下圖演示了一個包含分佈式事務的典型環境。

因爲存在事務管理器(Transaction Manager),它一般包含在應用程序服務器(Application Server)中,就再也不有兩層(Two-Tier)架構。傳統的客戶/服務器(Client/Server)架構已經由三層(Tree-Tier)架構 所取代,三層架構包含應用程序/客戶機、事務管理器(Transaction Manager)/應用程序服務器(Application Server)和數據庫服務器,而數據庫服務器通常稱做XA Resource

  1. 包含 SQL 和 JTA 調用的 Java 應用程序。
  2. 管理分佈式事務的應用程序服務器(Application Server)。
  3. 參與分佈式事務的數據庫。
  4. Java 應用程序嚮應用程序服務器(Application Server)提交常規 SQL 語句和通用的 XA 調用。
  5. 應用程序所發送的消息由應用程序服務器(Application Server)進行處理,並使用 SQL 和數據庫供應商特定的 XA 調用發送給數據庫。

一般,應用程序服務器(Application Server)提供了應用程序可使用的多種服務。在談到分佈式事務時,該服務就稱做XA Resource。固然,在應用程序可使用 XA Resource 以前,首先要在應用程序服務器中註冊和配置 XA Resource。

如今,若是您計劃在應用程序中使用 JTA,就必須修改代碼,以便還能夠與應用程序服務器(Application Server)進行通訊。這包括一些附加的方法調用和指定的錯誤/異常處理

分佈式事務:

在談到 XA 規範以前,必須首先了解分佈式事務處理( Distributed Transaction Processing , DTP )的概念。 Transaction ,即事務,又稱之爲交易,指一個程序或程序段,在一個或多個資源如 數據庫 或文件上爲完成某些功能的執行過程的集合。

分佈式事務處理是指一個事務可能涉及多個數據庫操做,分佈式事務處理的關鍵是必須有一種方法能夠知道事務在任何地方所作的全部動做,提交或回滾事務的決定必須產生統一的結果(所有提交或所有回滾)。

分佈式事務處理模型:

X/Open 組織(即如今的 Open Group )定義了分佈式事務處理模型。

X/Open DTP 模型( 1994 )包括:應用程序( AP )、事務管理器( TM )、資源管理器( RM )、通訊資源管理器( CRM )四部分。通常,常見的事務管理器( TM )是交易中間件,常見的資源管理器( RM )是數據庫,常見的通訊資源管理器( CRM )是消息中間件。

一般把一個數據庫內部的事務處理,如對多個表的操做,做爲本地事務看待。數據庫的事務處理對象是本地事務,而分佈式事務處理的對象是全局事務。

所謂全局事務,是指分佈式事務處理環境中,多個數據庫可能須要共同完成一個工做,這個工做便是一個全局事務,例如,一個事務中可能更新幾個不一樣的數據庫。對數據庫的操做發生在系統的各處,但必須所有被提交或回滾。此時一個數據庫對本身內部所作操做的提交不只依賴自己操做是否成功,還要依賴與全局事務相關的其它數據庫的操做是否成功,若是任一數據庫的任一操做失敗,則參與此事務的全部數據庫所作的全部操做都必須回滾。

通常狀況下,某一數據庫沒法知道其它數據庫在作什麼,所以,在一個 DTP 環境中,交易中間件是必需的,由它通知和協調相關數據庫的提交或回滾。而一個數據庫只將其本身所作的操做(可恢復)影射到全局事務中。

XA 就是 X/Open DTP 定義的交易中間件與數據庫之間的接口規範(即接口函數)。交易中間件用它來通知數據庫事務的開始、結束以及提交、回滾等。XA 接口函數由數據庫廠商提供。

XA協議包括兩套函數,以xa_開頭的及以ax_開頭的。

如下的函數使事務管理器能夠對資源管理器進行的操做:

1)xa_open,xa_close:創建和關閉與資源管理器的鏈接。

2)xa_start,xa_end:開始和結束一個本地事務。

3)xa_prepare,xa_commit,xa_rollback:預提交、提交和回滾一個本地事務。

4)xa_recover:回滾一個已進行預提交的事務。

5)ax_開頭的函數使資源管理器能夠動態地在事務管理器中進行註冊,並能夠對XID(TRANSACTION IDS)進行操做。

6)ax_reg,ax_unreg;容許一個資源管理器在一個TMS(TRANSACTION MANAGER SERVER)中動態註冊或撤消註冊。

JTA能夠處理任何提供符合XA接口的資源。包括:JDBC鏈接,數據庫,JMS,商業對象等等。

XA 與兩階段提交協議(Two-Phase-Commit):

一般狀況下,交易中間件與數據庫經過 XA 接口規範,使用兩階段提交來完成一個全局事務, XA 規範的基礎是兩階段提交協議。

第一階段:交易中間件請求全部相關數據庫準備提交(預提交)各自的事務分支,以確認是否全部相關數據庫均可以提交各自的事務分支。

當某一數據庫收到預提交後,若是能夠提交屬於本身的事務分支,則將本身在該事務分支中所作的操做固定記錄下來,並給交易中間件一個贊成提交的應答,此時數 據庫將不能再在該事務分支中加入任何操做,但此時數據庫並無真正提交該事務,數據庫對共享資源的操做還未釋放(處於上鎖狀態)。若是因爲某種緣由數據庫 沒法提交屬於本身的事務分支,它將回滾本身的全部操做,釋放對共享資源上的鎖,並返回給交易中間件失敗應答。

第二階段:交易中間件審查全部數據庫返回的預提交結果,如全部數據庫均可以提交,交易中間件將要求全部數據庫作正式提交,這樣該全局事務被提交。而若是有任一數據庫預提交返回失敗,交易中間件將要求全部其它數據庫回滾其操做,這樣該全局事務被回滾

以一個全局事務爲例, AP 首先通知交易中間件開始一個全局事務,交易中間件經過 XA 接口函數通知數據庫開始事務,而後 AP 能夠對數據庫管理的資源進行操做,數據庫系統記錄事務對本地資源的全部操做。操做完成後交易中間件經過 XA 接口函數通知數據庫操做完成。交易中間件負責記錄 AP 操做過哪些數據庫(事務分支)。 AP 根據狀況通知交易中間件提交該全局事務,交易中間件會經過 XA 接口函數要求各個數據庫作預提交,全部數據庫返回成功後要求各個數據庫作正式提交,此時一筆全局事務結束。

XA 規範對應用來講,最大好處在於事務的完整性由交易中間件和數據庫經過 XA 接口控制, AP 只須要關注與數據庫的應用邏輯的處理,而無需過多關心事務的完整性,應用設計開發會簡化不少。

具體來講,若是沒有交易中間件,應用系統須要在程序內部直接通知數據庫開始、結束和提交事務,當出現異常狀況時必須由專門的程序對數據庫進行反向操做才能完成回滾。若是是有不少事務分支的全局事務,回滾時狀況將變得異常複雜。而使用 XA 接口,則全局事務的提交是由交易中間件控制,應用程序只需通知交易中間件提交或回滾事務,就能夠控制整個事務(可能涉及多個異地的數據庫)的所有提交或回滾,應用程序徹底不用考慮衝正邏輯。

在一個涉及多個數據庫的全局事務中,爲保證全局事務的完整性,由交易中間件控制數據庫作兩階段提交是必要的。但 典型的兩階段提交,對數據庫來講事務從開始到結束(提交或回滾)時間相對較長,在事務處理期間數據庫使用的資源(如邏輯日誌、各類鎖),直到事務結束時才 會釋放。所以,使用典型的兩階段提交相對來講會佔用更多的資源,在網絡條件不是很好,如低速網、網絡顛簸頻繁,狀況會更爲嚴重。

當一個全局事務只涉及一個數據庫時,有一種優化方式,即一階段提交。當 AP 通知交易中間件提交事務時,交易中間件直接要求數據庫提交事務,省去兩階段提交中的第一階段,能夠縮短處理一個事務的時間,以提升事務處理的效率。做爲兩 階段提交的一種特例,與兩階段同樣,一階段提交也是標準的。

Two-phase commit

In an XA implementation, the transaction manager commits the distributed branches of a global transaction by using a two-phase commit protocol.

  1. In phase one, the transaction manager directs each resource manager to prepare to commit, which is to verify and guarantee it can commit its respective branch of the global transaction. If a resource manager cannot commit its branch, the transaction manager rolls back the entire transaction in phase two.

  2. In phase two, the transaction manager either directs each resource manager to commit its branch or, if a resource manager reported it was unable to commit in phase one, rolls back the global transaction.

Note the following optimizations:

  • If a global transaction is determined by the transaction manager to have involved only one branch, it skips phase one and commits the transaction in phase two.

  • If a global transaction branch is read-only, where it does not generate any transaction log records, the transaction manager commits the branch in phase one and skips phase two for that branch.

Note:

The transaction manager considers the global transaction committed if and only if all branches successfully commit.

兩階段提交詳細說明:

在分佈式系統中,事務每每包含有多個參與者的活動,單個參與者上的活動是可以保證原子性的,而多個參與者之間原子性的保證則須要經過兩階段提交來實現,兩階段提交是分佈式事務實現的關鍵。

很明顯,兩階段提交保證了分佈式事務的原子性,這些子事務要麼都作,要麼都不作。而數據庫的一致性是由數據庫的完整性約束實現的,持久性則是經過 commit日誌來實現的,不是由兩階段提交來保證的。至於兩階段提交如何保證隔離性,能夠參考Large-scale Incremental Processing Using Distributed Transactions and Notifications中兩階段提交的具體實現。

兩階段提交的過程涉及到協調者和參與者。協調者能夠看作成事務的發起者,同時也是事務的一個參與者。對於一個分佈式事務來講,一個事務是涉及到多個參與者的。具體的兩階段提交的過程以下:

第一階段:

首先,協調者在自身節點的日誌中寫入一條的日誌記錄,而後全部參與者發送消息prepare T,詢問這些參與者(包括自身),是否可以提交這個事務;

參與者在接受到這個prepare T 消息之後,會根據自身的狀況,進行事務的預處理,若是參與者可以提交該事務,則會將日誌寫入磁盤,並返回給協調者一個ready T信息,同時自身進入預提交狀態狀態;若是不能提交該事務,則記錄日誌,並返回一個not commit T信息給協調者,同時撤銷在自身上所作的數據庫改;

參與者可以推遲發送響應的時間,但最終仍是須要發送的。

第二階段:

協調者會收集全部參與者的意見,若是收到參與者發來的not commit T信息,則標識着該事務不能提交,協調者會將Abort T 記錄到日誌中,並向全部參與者發送一個Abort T 信息,讓全部參與者撤銷在自身上全部的預操做;

若是協調者收到全部參與者發來prepare T(ready T)信息,那麼協調者會將Commit T日誌寫入磁盤,並向全部參與者發送一個Commit T信息,提交該事務。若協調者遲遲未收到某個參與者發來的信息,則認爲該參與者發送了一個VOTE_ABORT信息,從而取消該事務的執行。

參與者接收到協調者發來的Abort T信息之後,參與者會終止提交,並將Abort T 記錄到日誌中;若是參與者收到的是Commit T信息,則會將事務進行提交,並寫入記錄。

通常狀況下,兩階段提交機制都能較好的運行,當在事務進行過程當中,有參與者宕機時,他重啓之後,能夠經過詢問其餘參與者或者協調者,從而知道這個事務到底提交了沒有。固然,這一切的前提都是各個參與者在進行每一步操做時,都會事先寫入日誌。

惟一一個兩階段提交不能解決的困境是:當協調者在發出commit T消息後宕機了,而惟一收到這條命令的一個參與者也宕機了,這個時候這個事務就處於一個未知的狀態,沒有人知道這個事務究竟是提交了仍是未提交,從而須要 數據庫管理員的介入,防止數據庫進入一個不一致的狀態。固然,若是有一個前提是:全部節點或者網絡的異常最終都會恢復,那麼這個問題就不存在了,協調者和 參與者最終會重啓,其餘節點也最終也會收到commit T的信息。

數據庫日誌保證了事務執行的原子性和持久性,日誌類型能夠分爲redo log,undo log,undo/redo log。關於這幾種日誌形式的具體介紹,能夠參照:http://nosql-wiki.org/foswiki/bin/view/Main/TransactonLog

相關文章
相關標籤/搜索