分布式事务

来源:互联网 发布:ubuntu 新建文档 编辑:程序博客网 时间:2024/06/10 20:30

参考博客: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事务

原创粉丝点击