2008-09-24 55 views
25

我有一個應用程序 - 更像是一個實用程序 - 位於角落並定期更新兩個不同的數據庫。什麼是使用Spring和Hibernate在多個數據庫上執行分佈式事務的「最佳」方式

這是一個有點獨立的應用程序,它是用Spring應用程序上下文構建的。上下文中配置了兩個Hibernate Session Factories,然後使用Spring中配置的Commons DBCP數據源。

目前沒有事務管理,但我想補充一些。對一個數據庫的更新取決於對另一個數據庫的成功更新。

該應用程序不在Java EE容器中 - 它由從shell腳本調用的靜態啓動器類引導。啓動程序類實例化應用程序上下文,然後在其一個bean上調用一個方法。

在數據庫更新中放置事務性的「最佳」方式是什麼?

我會給你留下'最好'的定義,但我認爲它應該是'容易設置','易於配置','便宜','易於打包和重新分配'的功能。 。自然,FOSS會很好。

回答

26

通過多個一個數據庫是:不。

有些人會指您XA,但XA(或兩階段提交)是謊言(或市場人)。

想象一下:在第一階段告訴XA管理員它可以發送最終提交後,到其中一個數據庫的網絡連接失敗。怎麼辦?時間到?這會使其他數據庫損壞。回滾?兩個問題:你不能回滾一個提交,你怎麼知道第二個數據庫發生了什麼?可能在成功提交數據後網絡連接失敗,只有「成功」消息丟失?

最好的方法是將數據複製到一個地方。使用允許您放棄副本並在任何時間繼續它的方案(例如,忽略您已擁有的數據或通過ID命令選擇並僅請求您的副本的記錄> MAX(ID))的方案。用交易來保護這一點。這不是問題,因爲您只是從源讀取數據,所以當事務因任何原因失敗時,您可以忽略源數據庫。因此,這是一個普通的單一來源交易。

複製數據後,在本地處理它。

+5

分佈式事務必須統計所有4個ACID屬性。你怎麼了?您所描述的場景不可能發生,因爲管理人員正在相互通信,並且只在所有參與節點交換了「GO」時才進行提交。 – Falcon 2011-01-05 11:24:19

6

在您的上下文中設置事務管理器。 Spring文檔有例子,它非常簡單。然後,當你要執行一個交易:

try { 
    TransactionTemplate tt = new TransactionTemplate(txManager); 

    tt.execute(new TransactionCallbackWithoutResult(){ 
    protected void doInTransactionWithoutResult(
      TransactionStatus status) { 
     updateDb1(); 
     updateDb2(); 
    } 
} catch (TransactionException ex) { 
    // handle 
} 

更多的例子,以及信息也許看看這個: XA transactions using Spring

+3

這個例子並沒有真正回答這個問題,或者它甚至錯誤地回答了:OP提到他有兩個Hibernate會話工廠被配置,這需要兩個單獨的事務管理器。答案中的示例僅使用一個未指定的事務管理器。因此,使用單個Hibernate事務管理器將永遠不會回滾這兩個DB中的一個出錯。例如使用「ChainedTransactionManager」(如@Pani Dhakshnamurthy所指出的)可能會有所幫助,但在這個答案中沒有提及。 – Chriki 2015-07-16 14:40:25

5

當你說「兩個不同的數據庫」,你的意思是不同的數據庫服務器,或同一個數據庫服務器中有兩種不同的模式?

如果前者,那麼如果你想要完全事務性,那麼你需要XA事務API,它提供了完整的兩階段提交。但更重要的是,您還需要一個事務協調器/監視器來管理不同數據庫系統之間的事務傳播。這是JavaEE規範的一部分,並且是其中一個相當稀少的部分。 TX協調器本身是一個複雜的軟件。你的應用軟件(通過Spring,如果你願意的話)與協調員進行交談。

但是,如果您只是指在同一個數據庫服務器中有兩個數據庫,那麼vanilla JDBC事務應該可以正常工作,只需在一個事務中針對兩個數據庫執行操作。

3

在這種情況下,您需要一個事務監視器(支持XA協議的服務器)並確保您的數據庫也支持XA。大多數(所有?)J2EE服務器都內置了Transaction Monitor。如果您的代碼不在J2EE服務器中運行,那麼有大量獨立的替代品 - Atomicos,Bitronix等。

相關問題