程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> WebSphere >> 在WebSphere JDBC Adapter中如何避免死鎖和鎖超時

在WebSphere JDBC Adapter中如何避免死鎖和鎖超時

編輯:WebSphere

簡介:在 WebSphere Process Server(WPS)中使用 WebSphere JDBC Adapter 的時候,要和數據庫進行頻繁的交互,執行數據庫操作、 事務使用以及管理。在高負載場景情況下,我們發現會有數據庫服務器報告有死鎖和鎖超時的現象。針對這個問題,本文首先引入在 WPS 上使 用 WebSphere JDBC Adapter 過程中死鎖和鎖超時發生的場景,然後介紹了 WPS 中對事務的管理,再進一步分析這些場景為什麼會產生死鎖和 鎖超時的現象,最後給出解決辦法去避免死鎖和鎖超時。

引言

WebSphere JDBC Adapter 是一個提供 J2EE 應用和數據庫供應商的 EIS 解決方案之間的連接的資源適配器,是構建在 WebSphere Process Server 之上的 WebSphere Adapter。不用應用之間的數據交換發生在數據庫層次,Adapter 使用 SQL 語句或存儲過程以業務對象 (Business Object, BO) 的形式來傳遞數據,實現數據庫與其他應用系統的集成。

WebSphere JDBC Adaper 可以集成任意構建在使用 JDBC 驅動(JDBC2.0 以上版本)的數據庫上的企業應用,基於 J2EE JCA 技術實現了 JDBC API,提供了 Inbound 和 Outbound 兩種操作來連接數據庫。其中,在 Outbound 操作下,BO 從應用系統傳遞到數據庫中,根據 BO 中 指定的動作(Create, Update, Delete, Retrieve, , RetrieveAll, Execute, Exists),BO 作為一個請求發送到 Adapter 中,Adapter 將 BO 傳遞到具體數據庫應用的表中。如果有需要,還可以進一步傳遞到其他構建在這個數據庫之上的應用系統中,並進行相應處理。在 outbound 操作中,將會涉及到數據庫的事務操作處理,繼而會產生數據庫的死鎖和鎖超時問題。接下來,看看死鎖和鎖超時分別在怎樣的場景 下會產生。

並發調用 WebSphere JDBC Adapter 的場景導致死鎖現象

當 WebSphere JDBC Adapter 在 outbound 組件被並發調用的情況下,很可能產生死鎖。在圖 1 中,我們可以看到 outbound 組件的 create,delete 操作被並發的調用很多次。更為普遍的是,當多次發起用戶請求的時候,會導致多線程場景。例如,outbound 組件在一個工 作流中被使用,用戶的多請求導致多個工作流並發的運行起來,也導致 outbound 組件也處在一個並發調用的情況下。

圖 1. BPEL 中的並發情況

當 outbound 組件在並發調用比較高的情況下,會拋出下面死鎖的異常信息:

清單 1. 死鎖異常信息

[12/30/09 13:23:22:078 CST] 00000055 FFDC
  Z com.ibm.ws.sca.internal.j2c.J2CMethodBindingImpl
  com.ibm.ws.sca.internal.j2c.J2CMethodBindingImpl#0x04 Exception:
  javax.resource.ResourceException: javax.resource.ResourceException:
   DB2 SQL Error: SQLCODE=-911, SQLSTATE=40001,
   SQLERRMC=2, DRIVER=3.50.152, error code: -911
  at com.ibm.j2ca.jdbc.commands.JDBCDeleteCommand.execute(JDBCDeleteCommand.java:379)
  at com.ibm.j2ca.extension.commandpattern.CommandForCursor.execute
  (CommandForCursor.java:68)
  at com.ibm.j2ca.extension.commandpattern.Interpreter.
    executeWithChildren(Interpreter.java:96)
  at com.ibm.j2ca.extension.commandpattern.Interpreter.execute(Interpreter.java:77)
  at com.ibm.j2ca.jdbc.JDBCInteraction.executeInternal(JDBCInteraction.java:358)
  at com.ibm.j2ca.jdbc.JDBCInteraction.execute(JDBCInteraction.java:139)
  at com.ibm.ws.sca.internal.j2c.J2CMethodBindingImpl.invoke(
  J2CMethodBindingImpl.java:242)

在特定場景下產生鎖超時

在圖 2 的場景之下,WebSphere JDBC Adapter 產生的兩個 outbound 組件加入到兩個不同的 BPEL 組件中。在這兩個 BPEL 組件中, “BPELGlobalTransaction”組件使用了全局事務,另外一個“BPELLocalTransaction”組件使用了本地事務。在 WebSphere JDBC Adapter 產 生的這兩個 outbound 組件中,使用全局事務的“globaltransaction”outbound 組件完成刪除主鍵為“1”的記錄的行為,另外一個使用本地 事務的“localtransaction”outbound 組件則要完成創建一個主鍵為“1”的記錄的行為。在這個場景中,使用了 DB2 數據庫,其數據庫參數 死鎖檢查時間和鎖超時檢查時間分別是“10”秒和“120”秒:

Interval for checking deadlock (ms) (DLCHKTIME) = 10000

Lock timeout (sec) (LOCKTIMEOUT) = 120

圖 2.在事務中運行的 WebSphere JDBC Adapter 的 outbound 組件

“BPELGlobalTransaction” 組件的內部業務邏輯比較復雜,在實際運行中要 5 分鐘左右時間才能夠完成。但是“BPELLocalTransaction ”組件卻比較簡單,只需要幾秒的時間就可以結束。首先啟動 “BPELGlobalTransaction”組件的運行,然後再啟動“BPELLocalTransaction ”組件的運行,大概 2 分多鐘之後,WebSphere Process Server 報告如下鎖超時的異常:

清單 1. 鎖超時異常信息

[12/30/09 11:38:29:062 CST] 00000072 FFDC Z
com.ibm.ws.sca.internal.j2c.J2CMethodBindingImpl
com.ibm.ws.sca.internal.j2c.J2CMethodBindingImpl#0x04 Exception:
javax.resource.ResourceException:
DB2 SQL Error: SQLCODE=-911, SQLSTATE=40001, SQLERRMC=68, DRIVER=3.50.152,
error code: -911
at com.ibm.j2ca.jdbc.JDBCDBOperationHandler.executePreparedCUDStatement
(JDBCDBOperationHandler.java:216)
at com.ibm.j2ca.jdbc.JDBCDBOperationHandler.executeSQL(
JDBCDBOperationHandler.java:646)
at com.ibm.j2ca.jdbc.commands.JDBCCreateCommand.execute(
JDBCCreateCommand.java:309)
at com.ibm.j2ca.extension.commandpattern.CommandForCursor.execute
(CommandForCursor.java:68)
at com.ibm.j2ca.extension.commandpattern.Interpreter.executeWithChildren
(Interpreter.java:96)
at com.ibm.j2ca.extension.commandpattern.Interpreter.execute(
Interpreter.java:77)
at com.ibm.j2ca.jdbc.JDBCInteraction.executeInternal(
JDBCInteraction.java:358)
at com.ibm.j2ca.jdbc.JDBCInteraction.execute(JDBCInteraction.java:139)
at com.ibm.ws.sca.internal.j2c.J2CMethodBindingImpl.invoke(
J2CMethodBindingImpl.java:242)

WebSphere Process Server 中 SCA 組件事務介紹

因為 WebSphere JDBC Adapter 運行在 WebSphere Process Server (WPS) 之上,其中對數據庫事務的控制和管理則是由 WPS 負責完成的 ,所以必須先了解相關的 WPS 的組件事務知識。

WebSphere Process Server (WPS) 是建立在 WebSphere 應用服務器上的新一代業務集成平台。它支持面向服務的應用架構和企業服務總線 ,含有符合業界標准的業務流程引擎,使用統一的服務調用和業務表現模型,並遵循業界的開放標准。服務組件架構(Service Component Architecture,SCA)是 WPS 新的編程模型,為其提供了統一的服務調用模型,也提供完整的事務支持。圖 3 是 SCA 的組件模型,一個 SCA 組件是由接口、服務實現和引用三個部分構成:

圖 3.SCA 組件模型

其中接口部分表示該組件能提供的業務能力;實現則是實現了該接口的組件;而引用則表示在服務實現中需要調用到的其他服務。在事務方 面,SCA 通過在三個部分(接口、服務實現和引用)分別提供不同的限定符(qualifier)的方式來完成事務的定制。

圖 4.接口上的事務限定符  

圖 4 顯示了接口部分的限定符有:Join Transaction。可以取值 true 或者 false。這個限定符表示該組件是否願意加入到調用方的事務 中。

圖 5. 實現上的事務限定符

圖 5 顯示了實現部分的限定符有:Transaction。 可以取值 Global、Local 或者 Any。這個限定符表示該組件對運行環境的需求。global 表示需要運行在一個全局事務中,這樣 SCA 容器必須保證在調用該服務實現時總是有一個活動的全局事務。local 則表示要運行在本地事務中 。容器必須掛起當前活動的全局事務,並負責啟動一個本地事務。any 則表示該實現既可以運行在一個已有的全局事務中也可以運行在本地事 務中。如果選擇了 any,容器如果發現當前沒有活動的事務,就會建立一個本地事務。

圖 6. 引用上的事務限定符

圖 6 顯示了引用部分的限定符有:Suspend transaction。取值為 true 或者 false。用來表示在調用這個目標服務時是否需要把當前的全 局事務掛起(但目標服務是否能加入到這個事務中,還取決於目標服務的事務配置)。如果選擇 true,則表示當前服務的事務不會被傳播給所 調用的服務。這個限定符只針對同步調用有效。

通過這三個部分的組合就可以實現細粒度的事務控制,這樣也就能對各個組件實現更為精確的事務控制。下面的表格 1 列舉出 Join transaction 和 transaction 兩種選項組合的情況下,如何實現對事務的管理和實現。

表 1. 目標組件的事務行為

接口
“Join Transaction”qualifier 實現
“Transaction” qualifier 目標組件的事務行為 True Global 如果目標組件已有全局事務的上下文環境,那麼目標組件就參與到已有全局事務中去;否則,運行時產生一個新的全局事務。 True Local 運行時產生一個錯誤,這個限定符的設置不對。 True Any 如果目標組件已有全局事務的上下文環境,那麼目標組件就參與到已有全局事務中去;否則,運行時產生一個新的本地事務。 False Global 目標組件運行在全局事務中,總是產生一個新的全局事務。 False Local 目標組件運行在本地事務中。 False Any 目標組件運行在本地事務中。

下面給一個具體例子,比如一個 SCA 組件有如下的事務需求:在運行時候需要有全局事務但不能加入到已有的全局事務中,該組件需要調 用到其他的服務,希望其他的服務也能加入到自己的事務中。那麼應該如下設計  :

接口的事務限定符應該設置為 join transaction=false,這樣就防止了該組件加入到上游的事務中;

實現上的事務限定符應該設置為 transaction=global。這樣 SCA 容器在調用該實現之前就會啟動一個全局事務;

引用上的事務限定符應該設置為 suspend transaction=false。這樣組件實現的事務就被允許傳播到被調用的服務;

WebSphere JDBC Adapter 中 outbound 組件事務介紹

WebSphere JDBC Adapter 的 outbound 組件只能在接口上進行事務限定符的配置,不可以在實現和引用上進行事務限定符的設置。

圖 7. WebSphere JDBC Adapter 的 outbound 組件上的事務限定符

在圖 7 中,WebSphere JDBC Adapter 只有接口上的事務限定符的設置,沒有提供實現和引用上的事務限定符的設置。從這點上來看,它既 符合了 SCA 組件的事務限定符的規則,同時又有它自己的特殊性。

此外,WebSphere JDBC Adapter 提供了三種連接方式,分別是“database URL mode”,“datasource JNDI mode”,“XA datasource name mode”。它們和 WebSphere JDBC Adapter 的 outbound 組件的事務有著很緊密的聯系。圖 8 中顯示了上面三種連接方式。

圖 8. WebSphere JDBC Adapter 的連接方式

WebSphere JDBC Adapter 根據接口上的事務限定符和三種連接方式確定 outbound 組件的事務行為,表格 2 中描述了各種組合之下產生的 事務行為。

表 2:WebSphere JDBC Adapter 的 outbound 組件的事務行為

接口
“Join Transaction” qualifier Outbound 組件采用的連接方式 outbound 組件的事務行為 True 使用“datasource JNDI mode”連接方式,且 datasource 是非 XA。
或者使用“database URL mode”的連接方式。 運行時產生一個錯誤,這個限定符的設置不對。 False 使用“datasource JNDI mode”連接方式,且 datasource 是非 XA。
或者使用“database URL mode”的連接方式。 outbound 組件運行在本地事務中。 True 使用“datasource JNDI mode”連接方式,且 datasource 是 XA。
或者使用“XA datasource name mode” 連接方式(僅適 用於 DB2,Oracle 數據庫)。 如果 outbound 組件已有全局事務的上下文環境,那麼 outbound 組件就參與到已有全局事務中去;否則,運行時產生一個新的全 局事務。 False 使用“datasource JNDI mode”連接方式,且 datasource 是 XA。
或者使用“XA datasource name mode”連接方式(僅適 用於 DB2,Oracle 數據庫) outbound 組件運行在本地事務中。

表格 2 中,當接口上的事務限定符是“join transaction=true”,同時采用“datasource JNDI mode”連接方式,且 WPS 上的 datasource 是 XA 類型的時候,它會在全局事務下運行;當接口上的事務限定符是“join transaction=false”,同時采用“datasource JNDI mode”連接方式,且 WPS 的 datasource 是 XA 類型的時候,它則會在本地事務下運行。

在了解了 WPS 的組件事務和 WebSphere JDBC Adapter 的 outbound 組件知識之後,接下來進一步分析死鎖和鎖超時是如何產生的。

死鎖是如何產生的

WebSphere JDBC Adapter 在並發情況下產生數據庫死鎖現象,僅僅出現在它采用“datasource JNDI mode”連接方式的時候。在 “datasource JNDI mode”連接方式下,WebSphere JDBC Adapter 使用了 WPS 的 Data Source。這個 Data Source 連接數據庫的時候,事務 隔離級別是被 WPS 的 Data Source 控制的,WebSphere JDBC Adapter 並沒有提供對事務隔離級別的控制。在缺省情況下,連接 DB2 和 MSSQLServer 的時候,WPS 上的 Data Source 事務隔離級別在被設置在“TRANSACTION_REPEATABLE_READ”下;在連接 Oracle 的時候,WPS 上的 Data Source 事務隔離級別在被設置在“TRANSACTION_READ_COMMITTED”下。同時,DB2、MSSQLServer、Oracle 數據庫端的缺省事務隔 離級別都是“TRANSACTION_READ_COMMITTED”。WPS 上的 Data Source 事務隔離級別優先級別高於數據庫端的隔離級別,所以當使用 WebSphere JDBC Adapter 的“datasource JNDI mode”連接方式去訪問 DB2 和 MSSQLServer 數據庫的時候,所產生的數據庫連接總是在 “TRANSACTION_REPEATABLE_READ”事務隔離級別下,它對事務的一致性和完整性要求比較高,會有死鎖現象的發生;但是,訪問 Oracle 數據 庫的時候,所產生的數據庫連接則是在“TRANSACTION_READ_COMMITTED”事務隔離級別下,不要求高的事務一致性和完整性,不會有死鎖現象 的發生。總之,在 WebSphere JDBC Adapter 被並發調用和在較高的事務隔離級別使用的情況下,會對數據庫中被訪問的表和行產生很多鎖, 以及出現鎖升級的情況,從而導致死鎖現象的發生。如果事務隔離級別設置的越高,數據完整性就越高,對並發支持和性能就會降低;如果事 務隔離級別設置的越低,對並發支持和性能提高越好,但是數據完整性就會降低。

如何解決死鎖問題

要解決死鎖問題,可以通過更改數據庫連接的事務隔離級別來達到消除死鎖現象的發生,具體的更改措施有如下幾種。

更改 WPS 上 Data Source 的缺省事務隔離級別,將缺省的“TRANSACTION_REPEATABLE_READ”事務隔離級別降低到 “TRANSACTION_READ_COMMITTED”,詳情請查閱“參考資料”一節。

更改 SCA component 上 EJB 的事務隔離級別,詳情請查閱“參考資料”一節。

當 WPS 上的 Data Source 事務隔離級別降低之後,應用程序對並發的支持和性能提高了,從而也就避免數據庫死鎖現象的發生。

鎖超時是怎麼產生的

在圖 2 場景中,DB2 數據庫端的死鎖檢查時間是 10 秒,鎖超時檢查時間是 120 秒,也就是說,在數據庫端,每過 10 秒中要檢查數據庫 中是否存在死鎖現象,每過 2 分鐘要檢查是否有鎖超時現象。在“globaltransaction”outbound 組件中,當它要執行刪除主鍵為“1”的記 錄的時候,因為同時它已加入到了“BPELGlobalTransaction”組件發起的全局事務中去,所以它必須等待這個 BPEL 組件所有業務邏輯操作全 部都執行完畢,這個刪除的操作才能最終提交到數據庫中去。在沒有執行完 BPEL 組件中所有的業務邏輯前,這個刪除操作一直不能提交到數 據庫。這會導致主鍵為“1”的記錄在數據庫上被鎖住不放。在這個場景中,由於這個 “BPELGlobalTransaction”組件執行完成需要 5 分鐘 的時間,所以數據庫會將這條主鍵為“1”的記錄鎖住 5 分鐘不放直至業務邏輯完成為止。當這條主鍵為“1”的記錄被鎖住的同時,第二個“ BPELLocalTransaction”組件也啟動了,它需要調用 “localtransaction”outbound 組件執行創建主鍵為“1”的記錄,此時數據庫會檢測到 這個記錄正在被另外一個應用鎖住了,所以“BPELLocalTransaction”組件不得不等待在這條記錄上鎖的釋放,過了 2 分鐘以後,數據庫檢查 到這個鎖仍然沒有釋放,但是鎖超時的時間已經到達,所以 WPS 報告鎖超時異常,終止“localtransaction”組件創建記錄的操作。通過以上 分析,如果 WebSphere JDBC Adapter 產生的 outbound 組件加入到一個全局事務中後,全局事務的時間過長會產生鎖超時的異常。

如何解決鎖超時問題

在上節的鎖超時問題分析中,因為 WebSphere JDBC Adapter 的一個 outbound 組件加入到上游組件的全局事務中去,且很可能這個上游組 件的全局事務執行完成所需要的時間超過了數據庫鎖超時的時間,在這種情況之下,又出現了其他的 WebSphere JDBC Adapter 的 outbound 組件也要訪問這個全局事務中已經訪問過的記錄,此刻就會出現鎖超時現象。為了避免這種現象,從設計上就要考慮,應該盡可能的使得全局 事務消耗的時間要短,在不同應用中要避免訪問相同的表或者記錄。當然,適當調整數據庫鎖超時時間也是可行方法之一。

總結

本文首先引入在 WebSphere JDBC Adapter 上產生死鎖和鎖超時的場景,然後介紹了 WPS 中 SCA 組件的事務特性,接著論述了 WebSphere JDBC Adapter 的 outbound 組件事務的特別之處,然後在實際應用中,針對事務引發的死鎖和鎖超時的現象尋找原因和進行分析,最後提供了 解決辦法去避免死鎖和鎖超時現象。

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