2015-01-01 36 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

相关问题