Java 分散式交易(多資料來源)

來源:互聯網
上載者:User

 

最近這幾天一直在整 怎麼實現分散式交易。找了很多資料,不過大都相近類同。對Oracle、SQL Server、Mysql數已做過測試,其中Mysql5.0以上的才支援分散式交易。

對於這些,主要是之前根本沒有接觸過分散式交易,還錯找了一些分布式事資料庫的資料,呵呵,結果不是我目前所需要的。
測試過程中出現了很多錯誤,一直都通不過,以為是使用者權限還有資料庫服務的問題,但一切都配置良好的情況下還一直都通不過。結果發現,我匯入的都是一些普通的JDBC串連包,於是狂搜實現XA事務的jar包。

Mysql:            mysql-connector-java-5.1.6-bin.jar
SQL Server:       sqljdbc.jar
Oracle:           ojdbc14.jar
用的是這些包才順利通過運行。後面會附上這幾個jar包。
好了,把原始碼也附上:

import com.microsoft.sqlserver.jdbc.SQLServerXADataSource;
import com.mysql.jdbc.jdbc2.optional.MysqlXADataSource;
import java.sql.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.sql.*;
import javax.transaction.xa.*;
import oracle.jdbc.xa.client.OracleXADataSource;

public class Mutil_DataSource_Test {
    public static void main(String[] args){
        Mutil_DataSource_Test mdt = new Mutil_DataSource_Test();
        try {
            mdt.test1();
        } catch (Exception ex) {
            System.out.println("除SQLException、XAException之外的異常: \n");
            Logger.getLogger(Mutil_DataSource_Test.class.getName()).log(Level.SEVERE, null, ex);

        }
    }

    class MyXid implements Xid{
        int formatId;
        byte globalTransactionId[];
        byte branchQualifier[];
        public MyXid(){

        }
        public MyXid(int formatId,byte[] globalTransactionId,byte[] branchQualifier){

            this.formatId = formatId;
            this.globalTransactionId = globalTransactionId;
            this.branchQualifier = branchQualifier;
        }

        public int getFormatId() {
            return this.formatId;
        }
        public void setFormatId(int formatId){
            this.formatId = formatId;
        }
        public byte[] getGlobalTransactionId() {
            return this.globalTransactionId;
        }
        public void setGlobalTransactionId(byte[] globalTransactionId){
            this.globalTransactionId = globalTransactionId;
        }
        public byte[] getBranchQualifier() {
            return this.branchQualifier;
        }
        public void setBranchQualifier(byte[] branchQualifier){
            this.branchQualifier = branchQualifier;
        }
    }

    //多資料庫測試
    public void test1() {
        //定義所需用到的變數
         Connection mysqlCn = null;
        Connection sqlCn = null;
        Connection mysqlCn2 = null;
        Connection oraCn = null;

        MysqlXADataSource mysqlDs = null;
        SQLServerXADataSource sqlDs = null;
        MysqlXADataSource mysqlDs2 = null;
        OracleXADataSource oraDs = null;

        XAConnection xamysqlCn = null;
        XAConnection xasqlCn = null;
        XAConnection xamysqlCn2 = null;
        XAConnection xaoraCn = null;

        XAResource xamysqlRes = null;
        XAResource xasqlRes = null;
        XAResource xamysqlRes2 = null;
        XAResource xaoraRes = null;

        Xid mysqlXid = null;
        Xid sqlXid = null;
        Xid mysqlXid2 = null;
        Xid oraXid = null;

        Statement mysqlpst = null;
        Statement sqlpst = null;
        Statement mysqlpst2 = null;
        Statement orapst = null;
    try{
        //獲得資料來源
        mysqlDs = new MysqlXADataSource();
        mysqlDs.setURL("jdbc:mysql://localhost:3306/test");
        mysqlDs2 = new MysqlXADataSource();
        mysqlDs2.setURL("jdbc:mysql://10.10.10.119:3306/test");
        sqlDs = new SQLServerXADataSource();
        sqlDs.setURL("jdbc:sqlserver://10.10.10.119:1433;DatabaseName=RTC;loginTimeout=20;user=sa;password=chgpwd122105");

//        sqlDs.setUser("sa");
//        sqlDs.setPassword("chgpwd122105");
//        sqlDs.setServerName("10.10.10.119");
//        sqlDs.setPortNumber(1433);
//        sqlDs.setDatabaseName("RTC");
        oraDs = new OracleXADataSource();
        oraDs.setURL("jdbc:oracle:thin:@10.10.10.119:1521:WMS");
        //獲得串連
        xamysqlCn = mysqlDs.getXAConnection("root", "9999");
System.out.println("xamysqlCn: "+xamysqlCn);
        xasqlCn = sqlDs.getXAConnection();
System.out.println("xasqlCn: "+xasqlCn);
        xamysqlCn2 = mysqlDs2.getXAConnection("root", "9999");
System.out.println("xamysqlCn2: "+xamysqlCn2);
        xaoraCn = oraDs.getXAConnection("tiger", "tiger");
System.out.println("xaoraCn: "+xaoraCn);

        mysqlCn = xamysqlCn.getConnection();
        sqlCn = xasqlCn.getConnection();
        mysqlCn2 = xamysqlCn2.getConnection();
        oraCn = xaoraCn.getConnection();

        mysqlpst = mysqlCn.createStatement();
        sqlpst = sqlCn.createStatement();
        mysqlpst2 = mysqlCn2.createStatement();
        orapst = oraCn.createStatement();
        //定義XAResource
        xamysqlRes = xamysqlCn.getXAResource();
        xasqlRes = xasqlCn.getXAResource();
        xamysqlRes2 = xamysqlCn2.getXAResource();
        xaoraRes = xaoraCn.getXAResource();
        //定義Xid
        mysqlXid = new MyXid(0, new byte[]{0x01}, new byte[]{0x02});
        sqlXid = new MyXid(0, new byte[]{0x01}, new byte[]{0x03});
        mysqlXid2 = new MyXid(0, new byte[]{0x01}, new byte[]{0x04});
        oraXid = new MyXid(0, new byte[]{0x01}, new byte[]{0x05});
        //執行Mysql
        xamysqlRes.start(mysqlXid, XAResource.TMNOFLAGS);       
        mysqlpst.executeUpdate("insert into test values(4,'XA','F','Class4')");
        xamysqlRes.end(mysqlXid, XAResource.TMSUCCESS);
        //執行SQLServer
        xasqlRes.start(sqlXid, XAResource.TMNOFLAGS);
        sqlpst.executeUpdate("insert into test values('444')");
        xasqlRes.end(sqlXid, XAResource.TMSUCCESS);
        //執行Mysql
        xamysqlRes2.start(mysqlXid2, XAResource.TMNOFLAGS);
        mysqlpst2.executeUpdate("insert into test values(4,'XA','F','Class4')");
        xamysqlRes2.end(mysqlXid2, XAResource.TMSUCCESS);
        //執行Oracle
        System.out.println("xaoraRes: "+xaoraRes);
        xaoraRes.start(oraXid, XAResource.TMNOFLAGS);
        orapst.executeUpdate("insert into test123 values('4','44','444')");
        System.out.println("oraXid: "+oraXid);
        xaoraRes.end(oraXid, XAResource.TMSUCCESS);
        //準備
        int mysqlRea = xamysqlRes.prepare(mysqlXid);
        int sqlRea = xasqlRes.prepare(sqlXid);
        int mysqlRea2 = xamysqlRes2.prepare(mysqlXid2);
        int oraRea = xaoraRes.prepare(oraXid);
        //判斷準備就緒與否  提交或復原
        if(mysqlRea == xamysqlRes.XA_OK && mysqlRea2 == xamysqlRes.XA_OK && oraRea == xaoraRes.XA_OK && sqlRea == xasqlRes.XA_OK){

//        if(mysqlRea == xamysqlRes.XA_OK && mysqlRea2 == xamysqlRes.XA_OK && oraRea == xaoraRes.XA_OK){

//        if(mysqlRea == xamysqlRes.XA_OK && sqlRea == xasqlRes.XA_OK && mysqlRea2 == xamysqlRes.XA_OK){

//        if(mysqlRea == xamysqlRes.XA_OK && mysqlRea2 == xamysqlRes.XA_OK){
            xamysqlRes.commit(mysqlXid, false);
System.out.println("Mysql 事務提交成功!");
            xasqlRes.commit(sqlXid, false);
System.out.println("SQLServer 事務提交成功!");
            xamysqlRes2.commit(mysqlXid2, false);
System.out.println("Mysql2 事務提交成功!");
            xaoraRes.commit(oraXid, false);
System.out.println("Oracle 事務提交成功!");
        }else{
            xamysqlRes.rollback(mysqlXid);
            xasqlRes.rollback(sqlXid);
            xamysqlRes2.rollback(mysqlXid2);
            xaoraRes.rollback(oraXid);
System.out.println("交易回復成功!");
        }
    }catch(SQLException ex){
        Logger.getLogger(Mutil_DataSource_Test.class.getName()).log(Level.SEVERE, null, ex);

        try{
            xamysqlRes.rollback(mysqlXid);
            xasqlRes.rollback(sqlXid);
            xamysqlRes2.rollback(mysqlXid2);
            xaoraRes.rollback(oraXid);
        }catch(XAException e){
            System.out.println("復原也出錯咯!~");
            e.printStackTrace();
        }
    }catch(XAException ex){
        Logger.getLogger(Mutil_DataSource_Test.class.getName()).log(Level.SEVERE, null, ex);

    }finally{
        try {
        //關閉
        mysqlpst.close();
        mysqlCn.close();
        xamysqlCn.close();
        sqlpst.close();
        sqlCn.close();
        xasqlCn.close();
        mysqlpst2.close();
        mysqlCn2.close();
        xamysqlCn2.close();
        orapst.close();
        oraCn.close();
        xaoraCn.close();
        } catch (SQLException ex) {
            Logger.getLogger(Mutil_DataSource_Test.class.getName()).log(Level.SEVERE, null, ex);

        }
    }
    }
}

分散式交易分為兩個階段,第一個階段相當於是一個預提交,第二階段才是正真的提交。
首先要實現的是Xid介面,formatId可以理解為一個全域事務的ID,不過我上面的代碼沒有去做一些異常的處理,還有正確的連結的關閉,只是自己做的一個小小的測試,以後項目中再去處理這些。第一階段如果出錯或是不順利則不會提交,需要做一些復原處理。如果順利則準備提交,進入第二階段,在第二階段可能會出現問題,如果第一個分支事務提交成功了,而後有一個分支事務提交失敗,這樣則會造成資料不準確,目前還不知道有沒有方法可以解決些問題,好像XAResource.recover()可以處理,但具體怎麼解決,在項目中自己還是可以想到辦法解決。

對XA分散式交易  我是初學者,而且也沒有誰指點,只是在網上找些資料。我上面的理解可能也還有些不足或是錯誤。希望高手看到後能指點指點。

  • XA_Jar包.rar (2.6 MB)
  • 下載次數: 106

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.