程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 權衡Apache Geronimo EJB事務選項,第3部分: 綜合所有事務

權衡Apache Geronimo EJB事務選項,第3部分: 綜合所有事務

編輯:關於JAVA

Jonathan Sagorin 在 由三部分組成的系列文章 的最後一部分中對 Enterprise Java™Beans(EJB)事務進行了全面的揭示。探索 Apache Geronimo 應用服務器上與容器管理事務和 bean 管理事務都相關的難題和附加實現與配置選項。

簡介

在本系列的 第 1 部分 和 第 2 部分 中,您簡單了解了 bean 管理的和容器管理的 EJB 事務以及如何在 Geronimo 應用服務器上實現它們。那麼接下來呢?在使用 EJB 事務時,您應考慮哪些其他事務設置是可用的,以及需要考慮的其他事項?

本文首先概述第 1 和第 2 部分中的事務選擇:容器管理或 bean 管理的事務。接著將了解並發控制策略和方法,確保事務執行時沒有數據損失。您還將了解隔離級別(如何控制事務與其他事務的隔離)並了解如何設置事務超時。最後,您將了解贊成和反對使用分布式事務的理由。

EJB 事務:我的選擇是什麼?

在實現 EJB 事務時,有兩種選擇:容器管理或 bean 管理的事務。

使用容器管理的事務時,將在部署描述符中指定事務行為。EJB 容器負責控制事務邊界。您為整個 enterprise bean、bean 上的個別方法或兩者指定事務屬性。事務屬性的選擇有:

Required

RequiresNew

Supports

Mandatory

NotSupported

Never

使用 bean 管理的事務時,您編程控制事務邊界並決定事務開始、提交和回滾的時機。在 bean 管理的事務中,可以在 Java Transaction API(JTA)或 Java Database Connectivity(JDBC)事務實現之間進行選擇。JTA 使用 javax.transaction.UserTransaction 接口控制事務,而 JDBC 事務則直接經 java.sql.Connection 接口執行操作來控制事務行為。

如果使用會話或消息驅動 bean(MDB),那麼可以實現 bean 管理或容器管理事務。然而,實體 bean 只可以使用容器管理事務。

表 1 按每個 enterprise bean 實現的事務類型總結了這些選擇。

表 1. enteprise bean 的事務類型選擇

事務類型 會話 bean 實體 bean 消息驅動 bean bean 管理 x   x 事務管理 x x x

如果不確定您的 bean 使用哪種事務類型,Sun Microsystems 建議對 enterprise bean 使用具有 required 屬性的容器管理的事務。

對於開發人員,使用容器管理的事務會比較簡單並且需更比較少的工作量。在 bean 方法中不要求事務邏輯。在 enterprise bean 的方法級別上劃分事務邊界。bean 方法必須運行在事務上下文中或不在其中運行。

如果要求對事務邊界進行更嚴格的控制,那麼使用 bean 管理的事務。如果期望在 enterprise bean 中擁有長期過程,那麼使用 bean 管理的事務。對於本文的目的,希望事務運行盡可能短的時間。如果使用容器管理事務,劃分邊界的粒度不夠細,它們處於 bean 方法級別。

通過使用 bean 管理的事務,可以限制事務的持續時間為短暫的。可以在事務中隔離數據庫操作並允許長期過程在事務作用域之外運行。這將確保不會阻塞訪問同一數據的其他任何事務。

並發控制策略

使用 EJB 實現並發控制有兩種策略:可以遵循消極(pessimistic)或積極(optimistic)鎖定策略。

使用消極鎖定 時,在修改數據所需的事務持續時間內獲取鎖,從而阻塞其他任何人修改同一數據。如果系統中有其他人可能試圖修改正在處理的數據,那麼這是使用該策略的好機會。該策略提供對數據的可靠訪問,但是不適用於較小規模的系統,因為當要求系統規模和更多鎖時,性能將會降低。

積極鎖定 不會在事務期間持有鎖。您采取積極的態度並假設在您使用數據時數據不會被其他事務修改。當發生數據沖突時,您可以處理異常情況,但假設這是很少發生的。當要求更新數據時,實現策略來檢查數據在最近被讀取之後和在被修改之前這段時間裡沒有發生改變。如果數據沒有改變,就執行更新。該策略適用於大規模系統。缺點是您必須實現檢測和處理數據沖突的代碼。

下一節將討論改變事務的隔離級別。這是消極鎖定的一個例子,其中通過改變事務的隔離級別來控制消極鎖定的程度和效力。

隔離

事務的 ACID 屬性之一是隔離性。隔離允許事務行為(無論是讀還是寫數據)獨立或隔離於其他並發運行的事務。通過控制隔離,每個事務在其行動時間裡都像是修改數據庫的惟一事務。一個事務與其他事務隔離的程度稱為隔離級別。

鎖機制和同步用來控制隔離級別。隨著隔離級別增加,需要更多的鎖和同步。由於鎖控制數據資源,其他嘗試執行任何數據操作的事務必須等待,直到鎖被釋放。因此,增加隔離級別將以性能為代價。相反,隨者隔離級別降低,因事務耗費較少的時間來等待鎖被釋放,將提高性能。

數據一致性

對事務設置隔離級別來處理下列數據一致性問題:

髒數據讀(Dirty read)

不可重復讀(Unrepeatable read)

影像讀(Phantom read)

髒數據讀

當從數據庫讀取未經提交的數據時,發生髒數據讀。讀取的數據沒有與數據庫裡的真實數據同步。

考慮下面的場景,其中兩個事務在讀取和更新數據庫的 String 字段 X。String X 的初始值是 foo:

事務 1 讀取 String X 的值 foo。

事務 1 將 String X 的當前值與 bar 連接並將其保存到數據庫中。

X 的新值是 foobar。事務 1 還沒有發出提交語句。

事務 2 讀取 String X 的值,即 foobar。

事務 1 中止。

事務 2 將 String X 與 bar 連接並將其保存至數據庫。

X 的新值是 foobarbar,這時其正確的值應該是 foobar。

事務 2 對 String X 的值執行了髒數據讀。

這裡的問題是一個事務可以改變值,而另一個事務可能在初始修改被提交前讀取其值。數據是髒的,並不能表示數據的真實狀態。

不可重復讀

如果應用程序從數據庫讀取數據,然後又重讀已經被修改的數據(可能以後在同一事務中),那麼會發生不可重復讀。考慮下面的場景,其中兩個應用程序在讀取和更新同一數據:

應用程序 1 讀取 String X 的值 foo。

應用程序 2 更新 String X 的值為 foobar。

應用程序 1 重讀 String 的值並發現其已改為 foobar。

因此在讀取之間,數據的值已改變並變得不一致。

影像讀

影像讀 與不可重復讀類似。但是,影像讀會將新數據插入到數據庫中。應用程序從數據庫中讀取數據集,然後確定在其重讀同一數據集時,附加的數據已經被添加。考慮下面的場景,其中兩個應用程序在讀取和更新數據庫的同一數據:

應用程序 1 搜索符合某個條件的數據並返回五行的數據集。

應用程序 2 將五個滿足應用程序 1 的搜索條件的附加行添加到數據庫。

在應用程序 1 基於其初始條件重讀數據庫(且期望得到五行)時,將返回 10 行。

同樣,在讀取之間數據變得不一致。

選擇隔離級別

隔離的四個級別列在下面,按最低(最弱)隔離級別到最高(最強)級別的順序排列。記住當提高隔離級別時,應用程序的性能將降低。

Read uncommitted - 該選項僅適用於具有非共享數據的非任務關鍵型系統(這在應用程序中是很少見的情況)。性能處於最佳狀態,但是將犧牲並發控制。如果確定沒有其他並發事務,請使用該選項。使用該選項,以上所列的數據問題都無法解決。

Read committed - 這是大多數數據庫的默認隔離級別,也是 Apache Geronimo 默認的。只能讀取提交的數據,因此該選項解決了髒數據讀問題。由於要求對數據庫使用附加鎖,因此性能將會慢一些。

Repeatable read - 通過使用該隔離級別,解決髒數據讀和未提交讀問題。可以保證讀取的任何行可以在以後被重讀而其值將不會改變。

Serializable - 這是最嚴格的隔離級別,解決了所有三個數據問題。在希望事務以真正隔離的方式運行並完全與其他事務獨立時,請使用該級別。這將保證數據一致性。對任務關鍵型系統使用它來保證真正地隔離事務行為。但是注意,該隔離級別是以性能為代價。

表 2 概述隔離級別選擇並顯示每個級別如何解決 早先 列出的三個數據問題。

表 2. 使用隔離級別解決數據問題

數據解決方案 Read uncommitted Read committed Repeatable read Serializable 解決髒數據讀   x x x 解決不可重復讀     x x 解決影像讀       x

在 bean 管理的事務中的隔離級別

通過底層的數據庫資源管理器指定隔離級別。使用 bean 管理的事務時,可以編程訪問底層連接。由於可以訪問 java.sql.Connection 接口,可以使用方法 setTransactionIsolation(int level) 改變連接的隔離級別。

使用下面這些常量來設置恰當的隔離級別:

Connection.TRANSACTION_READ_UNCOMMITTED

Connection.TRANSACTION_READ_COMMITTED

Connection.TRANSACTION_REPEATABLE_READ

Connection.TRANSACTION_SERIALIZABLE

其他讓人感興趣的方法是:

Connection.getTransactionIsolation()

DatabaseMetaData.supportsTransactionIsolationLevel(int)

(參考 參考資料 部分中的 Sun JavaDoc API 來獲得有關這些方法的更多信息。)

注意:通過修改隔離級別,要求數據庫資源管理器改變該資源的隔離性。這不是數據庫供應商必須提供的必要特性。實際上,很多數據庫供應商不會允許這麼做。在改變隔離級別時一定要小心。查看您的數據庫資源管理器文檔來查明支持的隔離級別。

另外,應該在開始事務之前設置事務隔離級別。決不能在事務的過程中切換隔離級別。大多數資源管理器還要求對事務中的所有參與者使用同一隔離級別。

在容器管理的事務中的隔離級別

在使用容器事務時,沒有辦法在部署描述符中指定隔離級別。默認情況下,Geronimo 對 EJB 容器使用 Read Committed 隔離級別。如果需要對隔離級別更細的控制,那麼考慮在 bean 管理的事務中使用 JDBC 事務。

事務超時

在 bean 管理的事務中使用 JTA 事務時,可以使用 javax.transaction.UserTransaction 接口的 setTransactionTimeout 方法。這將設置在事務中止之前將運行的最大時間(秒)。

分布式事務

在單個事務中的多個參與者物理分布於網絡中時,事務稱為分布式事務。分布式事務允許不同類型的資源參與到事務中。分布式事務的例子是:

單個會話 bean 開始事務並更新數據庫 A。調用運行在同一個應用服務器上的另一個會話 bean 來更新數據庫 B。第一個會話 bean 提交事務。兩個數據庫更新發生在同一個事務中。

單個會話 bean 開始事務並更新數據庫 A。調用運行在不同的 應用服務器上的另一個會話 bean 來更新數據庫 B。每個應用服務器的事務管理器將確保兩個數據庫在同一事務中更新。

單個會話 bean 開始事務並更新數據庫 A,接著是 Java Message Service(JMS)操作。兩個工作單元都是同一事務的一部分。如果 JMS 操作失敗,事務將不會更新數據庫。

幾個事務管理器必須共同工作來執行分布式事務。通常指定一個單獨的事務管理器(稱為事務協調器或分布式事務管理器)來協調其他事務管理器。

事務管理器進而與資源管理器進行協調來對資源(可能是數據庫或消息服務器)執行必需的提交或回滾。大多數數據庫的事務管理器和資源管理器緊密地耦合在一起。

兩段式提交

通過使用某種協議進行通信來完成分布式事務,被稱為兩段式提交。從名字上看,您可能已經知道有兩個階段:

第一個階段,即預提交:

事務協調器給每個事務管理器發送准備操作的信號。

事務管理器將操作(通常是數據更新)步驟(或細節)寫入事務日志。如果失敗,事務管理器使用這些步驟重復操作。

事務管理器本地創建事務並通知資源管理器對資源(例如,數據庫或消息服務器)執行操作。

資源管理器執行操作並向事務管理器報告成功(准備提交信號)或失敗(准備回滾)。

資源管理器等待事務管理器進一步的指令。

事務管理器向事務協調器報告成功或失敗。

第二階段,即提交階段:在第二階段中,第一階段的結果將傳送給所有事務管理器。如果任何事務管理器報告失敗,所有的事務參與者都必須回滾。

事務協調器讓所有事務管理器提交(或回滾)。

所有事務管理器將提交或回滾信息傳遞給其資源管理器。

資源管理器將成功或失敗提示返回給事務管理器。

事務管理器向事務協調器報告成功或失敗。

我們可以交談嗎?

分布式事務的最大挑戰是對事務管理器之間的共用通信協議取得一致。用於兩段式提交的標准化協議稱為 XA 協議,但是並非所有的供應商都支持該標准。XA 協議定義了事務管理器和資源管理器之間的接口。

Geronimo 的事務管理器是 Java Open Transaction Manager(JOTM),一個開放源碼的事務管理器。它實現 XA 協議並編譯成 JTA。記住,JTA 是本系列文章中用來與事務管理器進行通信的接口。可以在 bean 管理的事務中使用其來指定何時啟動、提交或回滾事務。

只要所有的事務參與者都對通信協議取得一致,它們就可以參與同一分布式事務。

它不是完美的

注意,使用分布式事務比使用本地事務要慢。所有事務參與者都需要更多的系統資源。事務協調器和所有事務參與者之間的網絡交流都將影響系統響應時間。分布式事務由於涉及的事務管理器和資源管理器的數量,還將花費更多時間。

結束語

在這個介紹性的 關於 EJB 事務的系列 的最後一部分中,您已看到對選擇的總結,並討論了在 Geronimo 中使用 EJB 事務的一些附加配置選項及選擇。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved