2015-01-01 35 views
0

我需要在覈心Java應用程序(不是web)中使用JTA XA資源和MySQL,而不使用任何框架。所有的文章和例子都顯示了使用單一數據源的提交。雖然我已經完成了兩個數據庫的分佈式事務,但是我在使用XA資源的'兩階段提交'中懷疑/查詢。我的代碼是:JTA XAResource多個數據庫:如果在準備後兩階段提交失敗會怎麼樣

public static void main(String[] args) { 
    DataSource dataSourceRemote = ConnectionManager.getDatasourceRemote(); 
    DataSource dataSourceLocal = ConnectionManager.getDatasourceLocal(); 
XAResource xaRes; 
    XAResource xaRes2; 
    XID xid, xid2; 
    try { 

     XADataSource xaDataSourceLocal; 
     XAConnection xaCon; 

     //XID xid; 
     Connection con; 
     Statement stmt; 
     int ret; 

     XADataSource xaDataSourceRemote; 
     XAConnection xaCon2; 

     //XID xid2; 
     Connection con2; 
     Statement stmt2; 
     int ret2;xaDataSourceLocal = (XADataSource) dataSourceLocal; 

     xaCon = xaDataSourceLocal.getXAConnection("root", "root"); 
     con = xaCon.getConnection(); 
     stmt = con.createStatement(); 
     xaRes = xaCon.getXAResource(); 

     xaDataSourceRemote = (XADataSource) dataSourceRemote; 

     xaCon2 = xaDataSourceRemote.getXAConnection("root", "root"); 
     con2 = xaCon2.getConnection(); 
     stmt2 = con2.createStatement(); 
     xaRes2 = xaCon2.getXAResource(); 

     con.setAutoCommit(false); 
     con2.setAutoCommit(false); 

     xid = new XID(100, new byte[] {0x01}, new byte[] {0x02}); 
     xid2 = new XID(101, new byte[] {0x02}, new byte[] {0x03}); 

     xaRes.start(xid, XAResource.TMNOFLAGS); 
     String query = "insert into emp values (12, \"Sanjay\", \"12345\", 100000)"; 
     System.out.println(query); 
     stmt.executeUpdate(query); 


     xaRes2.start(xid2, XAResource.TMNOFLAGS); 
     stmt2.executeUpdate("insert into emp values (11, \"Nikhil\", \"12345\",  100000)"); 


     xaRes2.end(xid2, XAResource.TMSUCCESS); 
     xaRes.end(xid, XAResource.TMSUCCESS);ret = xaRes.prepare(xid); 
     ret2 = xaRes2.prepare(xid2); 

     if(ret == XAResource.XA_OK && ret2 == XAResource.XA_OK){ 
      xaRes2.commit(xid2, false); 
      xaRes.commit(xid, false); 

     } 
     con.close(); 
     con2.close(); 
     xaCon.close(); 
     xaCon2.close(); 

     con2.close(); 
    } catch (XAException e) { 

     e.printStackTrace();    
    } 
    catch (SQLException e) { 

     e.printStackTrace(); 
    } 
} 

}

現在我的查詢是:

1)是否有任何需要定義兩個的Xid彷彿我的Xid取代Xid2,代碼運行正常

2)我已經在線調試:if(ret == XAResource.XA_OK & & ret2 == XAResource.XA_OK),當準備返回XAResource.XA_OK並且條件對於這兩個xresources都爲真。現在,如果我停止MySQL服務到我的本地機器,xaRes2.commit(xid2,false);會成功運行並且xaRes.commit(xid,false);會拋出XA異常。在這種情況下,「兩階段提交」失敗,因爲一個數據源處於不一致的狀態。 我的問題是,我做對了還是有其他的方式嗎?

3)什麼是實際使用中恢復,因爲在這種情況下,一個交易已經得到了COMMITED,我想你弄糊塗了其他失敗後準備成功

回答

0

1回)。 XA事務由XID標識/引用。所以如果你使用兩個xID,你將有兩個XA事務。

您可以在兩個不同的卡片中使用相同的XID,它們都可以是同一XA事務的一部分。

2)通常你有一個事務管理器來處理這個問題,並在發生錯誤時進行清理。在這種情況下,您基本上需要實現這一點,並且需要處理所有錯誤情況,這不是微不足道的。爲確保恢復部分正常工作,您需要測試所有不同的錯誤情況。舉例來說,Oracle允許您在提交代碼路徑中的不同位置提交失敗以進行測試。我不確定mysql具有相同的能力。

3)如果您的XA事務的某個分支失敗,或者如果您提交併且您的某個資源管理器無法提交,則需要恢復。

一般情況下,如果您在您的情況下使用Mysql等數據庫,則需要數據庫實施xa協議,否則恢復很可能無法正常工作。當然,你需要告訴數據庫,這是一個xa事務。

+0

你好Steave,MySQL的實現XA當我從得到的數據源 'MysqlDataSource數據源=新MysqlXADataSource();'。根據第一點的情況。 (2)如果一個數據源處於瞬態並引發XA異常,我怎樣才能將它置於一致的狀態?或者我如何在這種情況下恢復它?還有一件事,你能幫我解決這個問題嗎[鏈接](http://stackoverflow.com/questions/27854352/warning-executing-transaction-with-0-enlisted-resource-bitronix) – atv

相關問題