分布式事务 - MySQL外部XA事务

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yangliu19920502/article/details/78466753

参考博客:http://lixiaohui.iteye.com/blog/2352645
测试实现了Java版本的XA事务代码,这里使用的SQL实现,当然MySQL驱动实现了JTA,也可以使用MysqlXADataSource 做XA事务

首先检查MySQL是否开启XA事务:

SHOW VARIABLES LIKE '%xa%'

ON表示开启

数据库的XA事务实现都是数据库本身实现的,在多个不同数据库操作的时候由Java客户端和数据库驱动作为 <资源管理器> 所以不用操心MySQL是怎么配置协调多台数据库的

下面的例子和参考博客类似
A表中有一个用户余额为1000块钱
B表中有一个用户余额为1000块钱
3次修改后 A表余额 700 B表余额 1300
其中两次修改是由事务回滚无效

代码如下:

package com.myself.mysqlxa;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.UUID;

/**
 * @author yangankang
 */
public class XARun {

    static {
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws SQLException {
        XARun xaRun = new XARun();

        xaRun.xaSuccess(false, false);
        xaRun.xaSuccess(true, false);
        xaRun.xaSuccess(false, true);
    }

    public static Connection getConnection(String ip, String db, String user, String password, int port) throws SQLException {
        String url = "jdbc:mysql://" + ip + ":" + port + "/" + db + "?"
                + "user=" + user + "&password=" + password + "&useUnicode=true&characterEncoding=UTF8&autoReconnect=true";

        return DriverManager.getConnection(url);
    }

    private Connection getC1() throws SQLException {
        return XARun.getConnection("localhost", "mysql_xa", "root", "123456", 3307);
    }

    private Connection getC2() throws SQLException {
        return XARun.getConnection("localhost", "mysql_xa", "root", "123456", 3306);
    }

    /**
     * 假设两个不同的数据库的money是一样的1000
     *
     * @param ep1
     * @param ep2
     * @throws SQLException
     */
    public void xaSuccess(boolean ep1, boolean ep2) throws SQLException {
        String xid = UUID.randomUUID().toString().replace("-", "");
        Connection c1 = null;
        Connection c2 = null;
        Statement s1 = null;
        Statement s2 = null;
        try {
            c1 = this.getC1();
            c2 = this.getC2();
            s1 = c1.createStatement();
            s2 = c2.createStatement();
            s1.execute("XA START '" + xid + "'");
            s2.execute("XA START '" + xid + "'");

            s1.execute("UPDATE `user` SET `money` = `money` - 300 WHERE `name`='秦明涛'");
            s2.execute("UPDATE `user` SET `money` = `money` + 300 WHERE `name`='杨安康'");

            s1.execute("XA END " + "'" + xid + "'");
            s1.execute("XA PREPARE " + "'" + xid + "'");

            s2.execute("XA END " + "'" + xid + "'");
            s2.execute("XA PREPARE " + "'" + xid + "'");

            if (ep1) {
                throw new RuntimeException("事务回滚1");
            }

            s1.execute("XA COMMIT " + "'" + xid + "'");
            if (ep2) {
                throw new RuntimeException("事务回滚2");
            }
            s2.execute("XA COMMIT " + "'" + xid + "'");
        } catch (Exception e) {
            e.printStackTrace();
            if (s1 != null) {
                s1.execute("XA ROLLBACK " + "'" + xid + "'");
            }
            if (s2 != null) {
                s2.execute("XA ROLLBACK " + "'" + xid + "'");
            }
        } finally {
            try {
                if (c1 != null) c1.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
            try {
                if (c2 != null) c2.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

这就是MySQL的XA事务

猜你喜欢

转载自blog.csdn.net/yangliu19920502/article/details/78466753