Search in sources :

Example 6 with MysqlXid

use of com.mysql.cj.jdbc.MysqlXid in project aws-mysql-jdbc by awslabs.

the class DataSourceRegressionTest method testBug72890.

/**
 * Tests fix for BUG#72890 - Java jdbc driver returns incorrect return code when it's part of XA transaction
 *
 * @throws Exception
 */
@Test
public void testBug72890() throws Exception {
    MysqlXADataSource myDs = new MysqlXADataSource();
    myDs.setUrl(BaseTestCase.dbUrl);
    myDs.<SslMode>getEnumProperty(PropertyKey.sslMode).setValue(SslMode.DISABLED);
    myDs.getBooleanProperty(PropertyKey.allowPublicKeyRetrieval).setValue(true);
    try {
        final Xid xid = new MysqlXid("72890".getBytes(), "72890".getBytes(), 1);
        final XAConnection xaConn = myDs.getXAConnection();
        final XAResource xaRes = xaConn.getXAResource();
        final Connection dbConn = xaConn.getConnection();
        final long connId = ((MysqlConnection) ((MysqlConnection) dbConn).getConnectionMutex()).getSession().getThreadId();
        xaRes.start(xid, XAResource.TMNOFLAGS);
        xaRes.end(xid, XAResource.TMSUCCESS);
        assertEquals(XAResource.XA_OK, xaRes.prepare(xid));
        // Simulate a connection hang and make sure the connection really dies.
        this.stmt.execute("KILL CONNECTION " + connId);
        int connAliveChecks = 4;
        while (connAliveChecks > 0) {
            this.rs = this.stmt.executeQuery("SHOW PROCESSLIST");
            boolean connIsAlive = false;
            while (!connIsAlive && this.rs.next()) {
                connIsAlive = this.rs.getInt(1) == connId;
            }
            this.rs.close();
            if (connIsAlive) {
                connAliveChecks--;
                System.out.println("Connection id " + connId + " is still alive. Checking " + connAliveChecks + " more times.");
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                }
            } else {
                connAliveChecks = -1;
            }
        }
        assertFalse(connAliveChecks == 0, "Failed to kill the Connection id " + connId + " in a timely manner.");
        XAException xaEx = assertThrows(XAException.class, "Undetermined error occurred in the underlying Connection - check your data for consistency", new Callable<Void>() {

            public Void call() throws Exception {
                xaRes.commit(xid, false);
                return null;
            }
        });
        assertEquals(XAException.XAER_RMFAIL, xaEx.errorCode, "XAException error code");
        dbConn.close();
        xaConn.close();
    } finally {
        /*
             * After MySQL 5.7.7 a prepared XA transaction is no longer rolled back at disconnect. It needs to be rolled back manually to prevent test failures
             * in subsequent runs.
             * Other MySQL versions won't have any transactions to recover.
             */
        final XAConnection xaConnRecovery = myDs.getXAConnection();
        final XAResource xaResRecovery = xaConnRecovery.getXAResource();
        final Xid[] xidsToRecover = xaResRecovery.recover(XAResource.TMSTARTRSCAN);
        for (Xid xidToRecover : xidsToRecover) {
            xaResRecovery.rollback(xidToRecover);
        }
        xaConnRecovery.close();
    }
}
Also used : MysqlXADataSource(com.mysql.cj.jdbc.MysqlXADataSource) XAException(javax.transaction.xa.XAException) MysqlXid(com.mysql.cj.jdbc.MysqlXid) Connection(java.sql.Connection) XAConnection(javax.sql.XAConnection) PooledConnection(javax.sql.PooledConnection) JdbcConnection(com.mysql.cj.jdbc.JdbcConnection) MysqlConnection(com.mysql.cj.MysqlConnection) MysqlConnection(com.mysql.cj.MysqlConnection) XAException(javax.transaction.xa.XAException) SQLException(java.sql.SQLException) MysqlXid(com.mysql.cj.jdbc.MysqlXid) Xid(javax.transaction.xa.Xid) XAResource(javax.transaction.xa.XAResource) XAConnection(javax.sql.XAConnection) Test(org.junit.jupiter.api.Test)

Example 7 with MysqlXid

use of com.mysql.cj.jdbc.MysqlXid in project aws-mysql-jdbc by awslabs.

the class XATest method createXid.

private Xid createXid(Xid xidToBranch) throws IOException {
    ByteArrayOutputStream bqualOut = new ByteArrayOutputStream();
    DataOutputStream dataOut = new DataOutputStream(bqualOut);
    new UID().write(dataOut);
    final byte[] bqual = bqualOut.toByteArray();
    Xid xid = new MysqlXid(xidToBranch.getGlobalTransactionId(), bqual, 3306);
    return xid;
}
Also used : UID(java.rmi.server.UID) MysqlXid(com.mysql.cj.jdbc.MysqlXid) Xid(javax.transaction.xa.Xid) MysqlXid(com.mysql.cj.jdbc.MysqlXid) DataOutputStream(java.io.DataOutputStream) ByteArrayOutputStream(java.io.ByteArrayOutputStream)

Example 8 with MysqlXid

use of com.mysql.cj.jdbc.MysqlXid in project note by kebukeYi.

the class XATransaction method main.

public static void main(String[] args) {
    try {
        // ========================== START ==========================================//
        // 是否开启日志
        boolean isLogging = true;
        // 获取rm
        Connection conn1 = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/bank1?serverTimezone=UTC", "root", "123456");
        XAResource accountResource = new MysqlXAConnection((com.mysql.cj.jdbc.JdbcConnection) conn1, isLogging).getXAResource();
        Connection conn2 = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/bank2?serverTimezone=UTC", "root", "123456");
        XAResource redBagResource = new MysqlXAConnection((com.mysql.cj.jdbc.JdbcConnection) conn2, isLogging).getXAResource();
        // 开始XA事物
        // 全局事物
        byte[] globalId = UUID.randomUUID().toString().getBytes();
        // 标识
        int formatId = 1;
        // 分支事物一
        Xid xid1 = new MysqlXid(globalId, UUID.randomUUID().toString().getBytes(), formatId);
        // 分支事物二
        Xid xid2 = new MysqlXid(globalId, UUID.randomUUID().toString().getBytes(), formatId);
        try {
            // 分支事物1开始,此时状态:ACTIVE
            accountResource.start(xid1, XAResource.TMNOFLAGS);
            // 模拟业务
            conn1.prepareStatement("update account_info set account_balance=account_balance-10 where account_no=1").execute();
            accountResource.end(xid1, XAResource.TMSUCCESS);
            // 分支事物1 此时状态 IDLE
            // 分支事物2开始
            redBagResource.start(xid2, XAResource.TMNOFLAGS);
            // 模拟业务
            conn2.prepareStatement("update account_info set account_balance=account_balance+10 where account_no=2").execute();
            // 存在异常
            int i = 10 / 0;
            redBagResource.end(xid2, XAResource.TMSUCCESS);
            // 分支事物2 此时状态 IDLE
            // 第一阶段:准备提交
            int rm1_pre = accountResource.prepare(xid1);
            int rm2_pre = redBagResource.prepare(xid2);
            // XA事物 此时状态 PREPARED
            // 第二阶段: TM根据根据第一阶段的情况决定提交还是回滚
            // TM判断有两个事物分支,所以不能优化为一阶段提交
            boolean flag = false;
            if (rm1_pre == XAResource.XA_OK && rm2_pre == XAResource.XA_OK) {
                accountResource.commit(xid1, flag);
                redBagResource.commit(xid2, flag);
            } else {
                accountResource.rollback(xid1);
                redBagResource.rollback(xid2);
            }
        // ================= END =========================//
        } catch (Exception e) {
            // 出现异常,也要回滚
            try {
                accountResource.rollback(xid1);
                redBagResource.rollback(xid2);
                e.printStackTrace();
            } catch (XAException xaException) {
                xaException.printStackTrace();
            }
        }
    } catch (SQLException throwables) {
        throwables.printStackTrace();
    }
}
Also used : XAException(javax.transaction.xa.XAException) MysqlXid(com.mysql.cj.jdbc.MysqlXid) SQLException(java.sql.SQLException) Connection(java.sql.Connection) MysqlXAConnection(com.mysql.cj.jdbc.MysqlXAConnection) SQLException(java.sql.SQLException) XAException(javax.transaction.xa.XAException) XAResource(javax.transaction.xa.XAResource) MysqlXid(com.mysql.cj.jdbc.MysqlXid) Xid(javax.transaction.xa.Xid) MysqlXAConnection(com.mysql.cj.jdbc.MysqlXAConnection)

Aggregations

MysqlXid (com.mysql.cj.jdbc.MysqlXid)8 Xid (javax.transaction.xa.Xid)7 MysqlXAConnection (com.mysql.cj.jdbc.MysqlXAConnection)4 MysqlXADataSource (com.mysql.cj.jdbc.MysqlXADataSource)4 XAConnection (javax.sql.XAConnection)4 Test (org.junit.jupiter.api.Test)4 SuspendableXAConnection (com.mysql.cj.jdbc.SuspendableXAConnection)3 XAException (javax.transaction.xa.XAException)3 ByteArrayOutputStream (java.io.ByteArrayOutputStream)2 DataOutputStream (java.io.DataOutputStream)2 UID (java.rmi.server.UID)2 Connection (java.sql.Connection)2 SQLException (java.sql.SQLException)2 XAResource (javax.transaction.xa.XAResource)2 MysqlConnection (com.mysql.cj.MysqlConnection)1 JdbcConnection (com.mysql.cj.jdbc.JdbcConnection)1 PooledConnection (javax.sql.PooledConnection)1