2012-04-11 99 views
10

我正在實現涉及分佈式資源的兩階段提交。如何模擬參與數據庫的失敗?拔出網線不起作用,因爲它會導致表死鎖。我正在使用我的應用程序代碼中的鉤子,在查詢執行之後的不同點處拋出StaleConnectionException,執行查詢之後。我對這種方法的關注是:如何模擬數據庫故障以測試Java中的兩階段提交

  • 有沒有更好的方法來模擬數據庫故障?
  • 數據庫連接變差時連接對象會發生什麼變化?它保留其價值還是變爲空?
  • 應用程序嘗試重新連接到數據庫時實際發生了什麼?連接對象獲得了什麼值?它是否使用連接池中的現有值?

我也想在中間點來測試樣查詢執行過程中,在提交(後製備發送等)。現在,我將應用程序置於調試模式,並進入函數調用並插入它們之間的插件。但是這種方法是手動的,不適用於規模測試。

是否有模擬器/模擬器或工具可以幫助我做到這一點?

+0

您是否針對任何特定數據庫,或者這是否需要成爲任何JDBC連接數據庫的通用解決方案? – kgrittn 2012-04-11 15:27:04

+0

我現在正在使用DB2和DB2 z/OS。 – Andy 2012-04-11 16:13:13

+0

Andy,您選擇了哪種模擬數據庫故障的方法? – dmiandre 2013-09-11 14:26:22

回答

1

也許您可以添加自己的參與提交的資源,並在第一階段後暫停事務。同時你可以「拔插頭」。

+0

我不能添加比我已有的資源更多的資源。另外我不能控制他們的跑步,我不能停止並開始他們,因爲他們是開發數據庫。 – Andy 2012-04-11 16:14:30

+0

我認爲Andrej的意思是爭取另一個(虛擬)XAResource,它會觸發準備和提交之間的某種失敗。正確的方法是創建一個資源適配器。你也可以嘗試直接從你的應用程序中獲得XAResource,但我認爲WebSphere不允許通過標準的JTA API(請注意,通常這是J2EE不允許的)。您需要使用特定於WebSphere的API(因爲WebSphere在徵募XAResource時要求您生成所謂的「恢復令牌」)。 – 2012-04-11 18:47:51

1

Andrej回答了問題的一部分,所以讓我回答第二部分。

您在應用程序中獲得的Connection對象只是物理連接的包裝。該包裝器在連接池和事務管理中發揮作用。如果數據庫出現任何問題,連接包裝將無法使用,只能回滾。這是有道理的,因爲您僅在2PC啓動之前訪問連接,並且在2PC啓動之前完成的任何操作都無法恢復。

請注意,嘗試釋放連接並獲取新連接並不會改變任何內容,因爲一旦在事務中使用了來自給定數據源的連接,您將始終獲得與該數據源相同的連接因爲你在同一個交易中。這意味着如果不重新啓動整個事務,應用程序就不能「重新連接」。另一方面,如果在所有資源準備好之後但在所有資源都已提交之前出現問題,則事務管理器有責任恢復該事務。但是,這發生在幕後,你的應用程序無法控制。此時,您的應用程序預計將釋放該事務中使用的所有連接。

+0

Thnx詳細解釋。 我的情況發生了什麼事情:我在兩個數據庫上執行一個查詢作爲事務的一部分,並且就在它即將提交時,我拔出插件。應用程序拋出一個「javax.transaction.HeuristicMixedException」,然後嘗試回滾。現在,當TM(我的例子中是Websphere)試圖執行回滾時,它會得到以下模式:「發生了XAException,錯誤代碼是:XAER_NOTA(-4)ERRORCODE = -4228,SQLSTATE = null」。 然後我的qn是: 如果提交從未被調用,準備從未發送過。是否TM仍然會調用回滾? – Andy 2012-04-11 22:43:05

+0

此外,我的方法是拋出一個「StaleConnectionException」足以模擬數據庫失敗,還是我應該也釋放連接? – Andy 2012-04-11 22:46:43

0

你最好打賭的可能是在內存數據庫中使用。調用失敗並檢查數據源的前後狀態,以確保正確執行回滾/提交。

至於你的其他問題,這些似乎是非常高的成本/低迴報測試。閱讀您的供應商文檔,並確保您的交易環境已正確配置。一個這樣做你可能應該自動化,所以它的手。

除非您編寫了您自己的2PC協議特定的事務管理器+數據庫實現,否則我將離開測試這些功能您的供應商。

4

這是很多問題:)我會盡力完成以前的答案。

Is there a better way to simulate the DB failure? 

測試所有的情況是複雜的。測試主要案例的一種方法是創建JCA連接器(DB驅動程序是JCA連接器)。您可以從交易中徵募的連接器(第三方參與者)獲取連接。連接可能會引發某些錯誤。

有三個部分一起工作:(1)應用程序,(2)應用程序。服務器的事務管理器,以及(3)jca連接器(所謂的資源適配器)。

Communications between the three parts

的連接鉤到本身經由ManagedConnection.getXAResource交易。使用自定義jca連接器,您可以嚮應用程序(圖片中的Connection)或應用程序服務器的事務管理器(XAResource,通過圖中的ManagedConnection獲取)發出異常。您可以特別在XAResource.prepareXAResource.commit期間拋出異常,這對應於期間的錯誤的第2階段落實。

請注意,很難控制參與者的表達順序(請參閱this question)。因此很容易測試prepare之一失敗(即你的),但很難控制它們被調用的順序。複製兩階段提交的所有可能的無效狀態是複雜的,特別是在進行優化時。

(我寫一次JCA連接器(http://code.google.com/p/txfs),並有周圍的人,如果你想示例代碼。)

What happens to the connection object when DB connection goes bad? 
Does it retain its value or does it become null? 

ManagedConnection可以通知到事務管理器。其中一個通知是ConnectionEvent.CONNECTION_ERROR_OCCURRED,通知它使用此特定連接時發生錯誤。

正如在其他答案中指出的那樣,通常每個事務都有一個託管連接關聯。託管連接抽象了物理連接,並且您不想使用太多。該應用程序只獲取「句柄」(圖中的Connection)。在一個給定事務中獲得的句柄都指向相同的受管連接。這是大多數應用服務器支持的優化。

如果受管連接失效,則使用它的句柄也變得無效。但手柄可以AFAIK不被「刷新」。事務必須回滾,受管連接被銷燬。當另一個事務啓動時,它將與池中另一個有效的託管連接相關聯。

What actually happens when application tries to reconnect to DB? 
What value does connection object get? 
Does it use an existing value from the connection pool? 

應用服務器管理被管理的連接池。如前段所述,使用時可能會變壞。但是,如果不使用,也可能會變壞。例如,池中使用的託管連接可能會失效,因爲基礎物理連接超時。應用程序服務器通常具有一項功能,可以在開始使用它之前測試託管連接是否有效。如果沒有,它將嘗試從池中的另一個託管連接,或創建一個新連接。

+0

感謝您的詳細解釋。我還沒有時間來測試這一點呢。我會投票,一旦我去測試它,BT仍thnx 4這樣一個詳細的解釋 – Andy 2012-05-07 19:39:46

+0

希望它有幫助。你想做什麼並不容易。 (正如@ n​​sfyn55所寫,有「極高的成本/低迴報」) – ewernli 2012-05-08 06:21:27