Search in sources :

Example 1 with CoordinatorLogEntry

use of io.mycat.backend.mysql.xa.CoordinatorLogEntry in project Mycat_plus by coderczp.

the class MycatServer method performXARecoveryLog.

// XA recovery log check
private void performXARecoveryLog() {
    // fetch the recovery log
    CoordinatorLogEntry[] coordinatorLogEntries = getCoordinatorLogEntries();
    for (int i = 0; i < coordinatorLogEntries.length; i++) {
        CoordinatorLogEntry coordinatorLogEntry = coordinatorLogEntries[i];
        boolean needRollback = false;
        for (int j = 0; j < coordinatorLogEntry.participants.length; j++) {
            ParticipantLogEntry participantLogEntry = coordinatorLogEntry.participants[j];
            if (participantLogEntry.txState == TxState.TX_PREPARED_STATE) {
                needRollback = true;
                break;
            }
        }
        if (needRollback) {
            for (int j = 0; j < coordinatorLogEntry.participants.length; j++) {
                ParticipantLogEntry participantLogEntry = coordinatorLogEntry.participants[j];
                // XA rollback
                String xacmd = "XA ROLLBACK " + coordinatorLogEntry.id + ';';
                OneRawSQLQueryResultHandler resultHandler = new OneRawSQLQueryResultHandler(new String[0], new XARollbackCallback());
                outloop: for (SchemaConfig schema : MycatServer.getInstance().getConfig().getSchemas().values()) {
                    for (TableConfig table : schema.getTables().values()) {
                        for (String dataNode : table.getDataNodes()) {
                            PhysicalDBNode dn = MycatServer.getInstance().getConfig().getDataNodes().get(dataNode);
                            if (dn.getDbPool().getSource().getConfig().getIp().equals(participantLogEntry.uri) && dn.getDatabase().equals(participantLogEntry.resourceName)) {
                                // XA STATE ROLLBACK
                                participantLogEntry.txState = TxState.TX_ROLLBACKED_STATE;
                                SQLJob sqlJob = new SQLJob(xacmd, dn.getDatabase(), resultHandler, dn.getDbPool().getSource());
                                sqlJob.run();
                                LOGGER.debug(String.format("[XA ROLLBACK] [%s] Host:[%s] schema:[%s]", xacmd, dn.getName(), dn.getDatabase()));
                                break outloop;
                            }
                        }
                    }
                }
            }
        }
    }
    // init into in memory cached
    for (int i = 0; i < coordinatorLogEntries.length; i++) {
        MultiNodeCoordinator.inMemoryRepository.put(coordinatorLogEntries[i].id, coordinatorLogEntries[i]);
    }
    // discard the recovery log
    MultiNodeCoordinator.fileRepository.writeCheckpoint(MultiNodeCoordinator.inMemoryRepository.getAllCoordinatorLogEntries());
}
Also used : OneRawSQLQueryResultHandler(io.mycat.sqlengine.OneRawSQLQueryResultHandler) PhysicalDBNode(io.mycat.backend.datasource.PhysicalDBNode) SchemaConfig(io.mycat.config.model.SchemaConfig) ParticipantLogEntry(io.mycat.backend.mysql.xa.ParticipantLogEntry) SQLJob(io.mycat.sqlengine.SQLJob) XARollbackCallback(io.mycat.backend.mysql.xa.XARollbackCallback) TableConfig(io.mycat.config.model.TableConfig) CoordinatorLogEntry(io.mycat.backend.mysql.xa.CoordinatorLogEntry)

Example 2 with CoordinatorLogEntry

use of io.mycat.backend.mysql.xa.CoordinatorLogEntry in project Mycat-Server by MyCATApache.

the class MultiNodeCoordinator method executeBatchNodeCmd.

/**
 * Multi-nodes 1pc Commit Handle *
 */
public void executeBatchNodeCmd(SQLCtrlCommand cmdHandler) {
    this.cmdHandler = cmdHandler;
    final int initCount = session.getTargetCount();
    runningCount.set(initCount);
    nodeCount = initCount;
    failed.set(false);
    faileCount.set(0);
    // recovery nodes log
    ParticipantLogEntry[] participantLogEntry = new ParticipantLogEntry[initCount];
    // 执行
    int started = 0;
    for (RouteResultsetNode rrn : session.getTargetKeys()) {
        if (rrn == null) {
            LOGGER.error("null is contained in RoutResultsetNodes, source = " + session.getSource());
            continue;
        }
        final BackendConnection conn = session.getTarget(rrn);
        if (conn != null) {
            conn.setResponseHandler(this);
            // process the XA_END XA_PREPARE Command
            if (conn instanceof MySQLConnection) {
                MySQLConnection mysqlCon = (MySQLConnection) conn;
                String xaTxId = null;
                if (session.getXaTXID() != null) {
                    xaTxId = session.getXaTXID() + ",'" + mysqlCon.getSchema() + "'";
                }
                if (mysqlCon.getXaStatus() == TxState.TX_STARTED_STATE) {
                    // recovery Log
                    participantLogEntry[started] = new ParticipantLogEntry(xaTxId, conn.getHost(), 0, conn.getSchema(), ((MySQLConnection) conn).getXaStatus());
                    String[] cmds = new String[] { "XA END " + xaTxId, "XA PREPARE " + xaTxId };
                    if (LOGGER.isDebugEnabled()) {
                        LOGGER.debug("Start execute the batch cmd : " + cmds[0] + ";" + cmds[1] + "," + "current connection:" + conn.getHost() + ":" + conn.getPort());
                    }
                    mysqlCon.execBatchCmd(cmds);
                } else {
                    // recovery Log
                    participantLogEntry[started] = new ParticipantLogEntry(xaTxId, conn.getHost(), 0, conn.getSchema(), ((MySQLConnection) conn).getXaStatus());
                    cmdHandler.sendCommand(session, conn);
                }
            } else {
                cmdHandler.sendCommand(session, conn);
            }
            ++started;
        }
    }
    // xa recovery log
    if (session.getXaTXID() != null) {
        CoordinatorLogEntry coordinatorLogEntry = new CoordinatorLogEntry(session.getXaTXID(), false, participantLogEntry);
        inMemoryRepository.put(session.getXaTXID(), coordinatorLogEntry);
        fileRepository.writeCheckpoint(inMemoryRepository.getAllCoordinatorLogEntries());
    }
    if (started < nodeCount) {
        runningCount.set(started);
        LOGGER.warn("some connection failed to execute " + (nodeCount - started));
        /**
         * assumption: only caused by front-end connection close. <br/>
         * Otherwise, packet must be returned to front-end
         */
        failed.set(true);
    }
}
Also used : BackendConnection(io.mycat.backend.BackendConnection) ParticipantLogEntry(io.mycat.backend.mysql.xa.ParticipantLogEntry) RouteResultsetNode(io.mycat.route.RouteResultsetNode) MySQLConnection(io.mycat.backend.mysql.nio.MySQLConnection) CoordinatorLogEntry(io.mycat.backend.mysql.xa.CoordinatorLogEntry)

Example 3 with CoordinatorLogEntry

use of io.mycat.backend.mysql.xa.CoordinatorLogEntry in project Mycat_plus by coderczp.

the class MultiNodeCoordinator method executeBatchNodeCmd.

/**
 * Multi-nodes 1pc Commit Handle *
 */
public void executeBatchNodeCmd(SQLCtrlCommand cmdHandler) {
    this.cmdHandler = cmdHandler;
    final int initCount = session.getTargetCount();
    runningCount.set(initCount);
    nodeCount = initCount;
    failed.set(false);
    faileCount.set(0);
    // recovery nodes log
    ParticipantLogEntry[] participantLogEntry = new ParticipantLogEntry[initCount];
    // 执行
    int started = 0;
    for (RouteResultsetNode rrn : session.getTargetKeys()) {
        if (rrn == null) {
            LOGGER.error("null is contained in RoutResultsetNodes, source = " + session.getSource());
            continue;
        }
        final BackendConnection conn = session.getTarget(rrn);
        if (conn != null) {
            conn.setResponseHandler(this);
            // process the XA_END XA_PREPARE Command
            if (conn instanceof MySQLConnection) {
                MySQLConnection mysqlCon = (MySQLConnection) conn;
                String xaTxId = null;
                if (session.getXaTXID() != null) {
                    xaTxId = session.getXaTXID() + ",'" + mysqlCon.getSchema() + "'";
                }
                if (mysqlCon.getXaStatus() == TxState.TX_STARTED_STATE) {
                    // recovery Log
                    participantLogEntry[started] = new ParticipantLogEntry(xaTxId, conn.getHost(), 0, conn.getSchema(), ((MySQLConnection) conn).getXaStatus());
                    String[] cmds = new String[] { "XA END " + xaTxId, "XA PREPARE " + xaTxId };
                    if (LOGGER.isDebugEnabled()) {
                        LOGGER.debug("Start execute the batch cmd : " + cmds[0] + ";" + cmds[1] + "," + "current connection:" + conn.getHost() + ":" + conn.getPort());
                    }
                    mysqlCon.execBatchCmd(cmds);
                } else {
                    // recovery Log
                    participantLogEntry[started] = new ParticipantLogEntry(xaTxId, conn.getHost(), 0, conn.getSchema(), ((MySQLConnection) conn).getXaStatus());
                    cmdHandler.sendCommand(session, conn);
                }
            } else {
                cmdHandler.sendCommand(session, conn);
            }
            ++started;
        }
    }
    // xa recovery log
    if (session.getXaTXID() != null) {
        CoordinatorLogEntry coordinatorLogEntry = new CoordinatorLogEntry(session.getXaTXID(), false, participantLogEntry);
        inMemoryRepository.put(session.getXaTXID(), coordinatorLogEntry);
        fileRepository.writeCheckpoint(inMemoryRepository.getAllCoordinatorLogEntries());
    }
    if (started < nodeCount) {
        runningCount.set(started);
        LOGGER.warn("some connection failed to execute " + (nodeCount - started));
        /**
         * assumption: only caused by front-end connection close. <br/>
         * Otherwise, packet must be returned to front-end
         */
        failed.set(true);
    }
}
Also used : BackendConnection(io.mycat.backend.BackendConnection) ParticipantLogEntry(io.mycat.backend.mysql.xa.ParticipantLogEntry) RouteResultsetNode(io.mycat.route.RouteResultsetNode) MySQLConnection(io.mycat.backend.mysql.nio.MySQLConnection) CoordinatorLogEntry(io.mycat.backend.mysql.xa.CoordinatorLogEntry)

Example 4 with CoordinatorLogEntry

use of io.mycat.backend.mysql.xa.CoordinatorLogEntry in project Mycat_plus by coderczp.

the class MultiNodeCoordinator method okResponse.

@Override
public void okResponse(byte[] ok, BackendConnection conn) {
    // process the XA Transatcion 2pc commit
    if (conn instanceof MySQLConnection) {
        MySQLConnection mysqlCon = (MySQLConnection) conn;
        switch(mysqlCon.getXaStatus()) {
            case TxState.TX_STARTED_STATE:
                // should be wait all nodes ready ,then send xa commit to all nodes.
                if (mysqlCon.batchCmdFinished()) {
                    String xaTxId = session.getXaTXID();
                    String cmd = "XA COMMIT " + xaTxId + ",'" + mysqlCon.getSchema() + "'";
                    if (LOGGER.isDebugEnabled()) {
                        LOGGER.debug("Start execute the cmd :" + cmd + ",current host:" + mysqlCon.getHost() + ":" + mysqlCon.getPort());
                    }
                    // recovery log
                    CoordinatorLogEntry coordinatorLogEntry = inMemoryRepository.get(xaTxId);
                    for (int i = 0; i < coordinatorLogEntry.participants.length; i++) {
                        LOGGER.debug("[In Memory CoordinatorLogEntry]" + coordinatorLogEntry.participants[i]);
                        if (coordinatorLogEntry.participants[i].resourceName.equals(conn.getSchema())) {
                            coordinatorLogEntry.participants[i].txState = TxState.TX_PREPARED_STATE;
                        }
                    }
                    inMemoryRepository.put(xaTxId, coordinatorLogEntry);
                    fileRepository.writeCheckpoint(inMemoryRepository.getAllCoordinatorLogEntries());
                    // send commit
                    mysqlCon.setXaStatus(TxState.TX_PREPARED_STATE);
                    mysqlCon.execCmd(cmd);
                }
                return;
            case TxState.TX_PREPARED_STATE:
                {
                    // recovery log
                    String xaTxId = session.getXaTXID();
                    CoordinatorLogEntry coordinatorLogEntry = inMemoryRepository.get(xaTxId);
                    for (int i = 0; i < coordinatorLogEntry.participants.length; i++) {
                        if (coordinatorLogEntry.participants[i].resourceName.equals(conn.getSchema())) {
                            coordinatorLogEntry.participants[i].txState = TxState.TX_COMMITED_STATE;
                        }
                    }
                    inMemoryRepository.put(xaTxId, coordinatorLogEntry);
                    fileRepository.writeCheckpoint(inMemoryRepository.getAllCoordinatorLogEntries());
                    // XA reset status now
                    mysqlCon.setXaStatus(TxState.TX_INITIALIZE_STATE);
                    break;
                }
            default:
        }
    }
    if (this.cmdHandler.relaseConOnOK()) {
        session.releaseConnection(conn);
    } else {
        session.releaseConnectionIfSafe(conn, LOGGER.isDebugEnabled(), false);
    }
    if (this.finished()) {
        cmdHandler.okResponse(session, ok);
        if (cmdHandler.isAutoClearSessionCons()) {
            session.clearResources(false);
        }
        /* 1.  事务提交后,xa 事务结束   */
        if (session.getXaTXID() != null) {
            session.setXATXEnabled(false);
        }
        /* 2. preAcStates 为true,事务结束后,需要设置为true。preAcStates 为ac上一个状态    */
        if (session.getSource().isPreAcStates()) {
            session.getSource().setAutocommit(true);
        }
    }
}
Also used : MySQLConnection(io.mycat.backend.mysql.nio.MySQLConnection) CoordinatorLogEntry(io.mycat.backend.mysql.xa.CoordinatorLogEntry)

Example 5 with CoordinatorLogEntry

use of io.mycat.backend.mysql.xa.CoordinatorLogEntry in project Mycat-Server by MyCATApache.

the class MultiNodeCoordinator method okResponse.

@Override
public void okResponse(byte[] ok, BackendConnection conn) {
    // process the XA Transatcion 2pc commit
    if (conn instanceof MySQLConnection) {
        MySQLConnection mysqlCon = (MySQLConnection) conn;
        switch(mysqlCon.getXaStatus()) {
            case TxState.TX_STARTED_STATE:
                // should be wait all nodes ready ,then send xa commit to all nodes.
                if (mysqlCon.batchCmdFinished()) {
                    String xaTxId = session.getXaTXID();
                    String cmd = "XA COMMIT " + xaTxId + ",'" + mysqlCon.getSchema() + "'";
                    if (LOGGER.isDebugEnabled()) {
                        LOGGER.debug("Start execute the cmd :" + cmd + ",current host:" + mysqlCon.getHost() + ":" + mysqlCon.getPort());
                    }
                    // recovery log
                    CoordinatorLogEntry coordinatorLogEntry = inMemoryRepository.get(xaTxId);
                    for (int i = 0; i < coordinatorLogEntry.participants.length; i++) {
                        LOGGER.debug("[In Memory CoordinatorLogEntry]" + coordinatorLogEntry.participants[i]);
                        if (coordinatorLogEntry.participants[i].resourceName.equals(conn.getSchema())) {
                            coordinatorLogEntry.participants[i].txState = TxState.TX_PREPARED_STATE;
                        }
                    }
                    inMemoryRepository.put(xaTxId, coordinatorLogEntry);
                    fileRepository.writeCheckpoint(inMemoryRepository.getAllCoordinatorLogEntries());
                    // send commit
                    mysqlCon.setXaStatus(TxState.TX_PREPARED_STATE);
                    mysqlCon.execCmd(cmd);
                }
                return;
            case TxState.TX_PREPARED_STATE:
                {
                    // recovery log
                    String xaTxId = session.getXaTXID();
                    CoordinatorLogEntry coordinatorLogEntry = inMemoryRepository.get(xaTxId);
                    for (int i = 0; i < coordinatorLogEntry.participants.length; i++) {
                        if (coordinatorLogEntry.participants[i].resourceName.equals(conn.getSchema())) {
                            coordinatorLogEntry.participants[i].txState = TxState.TX_COMMITED_STATE;
                        }
                    }
                    inMemoryRepository.put(xaTxId, coordinatorLogEntry);
                    fileRepository.writeCheckpoint(inMemoryRepository.getAllCoordinatorLogEntries());
                    // XA reset status now
                    mysqlCon.setXaStatus(TxState.TX_INITIALIZE_STATE);
                    break;
                }
            default:
        }
    }
    if (this.cmdHandler.relaseConOnOK()) {
        session.releaseConnection(conn);
    } else {
        session.releaseConnectionIfSafe(conn, LOGGER.isDebugEnabled(), false);
    }
    if (this.finished()) {
        cmdHandler.okResponse(session, ok);
        if (cmdHandler.isAutoClearSessionCons()) {
            session.clearResources(false);
        }
        /* 1.  事务提交后,xa 事务结束   */
        if (session.getXaTXID() != null) {
            session.setXATXEnabled(false);
        }
        /* 2. preAcStates 为true,事务结束后,需要设置为true。preAcStates 为ac上一个状态    */
        if (session.getSource().isPreAcStates()) {
            session.getSource().setAutocommit(true);
        }
    }
}
Also used : MySQLConnection(io.mycat.backend.mysql.nio.MySQLConnection) CoordinatorLogEntry(io.mycat.backend.mysql.xa.CoordinatorLogEntry)

Aggregations

CoordinatorLogEntry (io.mycat.backend.mysql.xa.CoordinatorLogEntry)6 MySQLConnection (io.mycat.backend.mysql.nio.MySQLConnection)4 ParticipantLogEntry (io.mycat.backend.mysql.xa.ParticipantLogEntry)4 BackendConnection (io.mycat.backend.BackendConnection)2 PhysicalDBNode (io.mycat.backend.datasource.PhysicalDBNode)2 XARollbackCallback (io.mycat.backend.mysql.xa.XARollbackCallback)2 SchemaConfig (io.mycat.config.model.SchemaConfig)2 TableConfig (io.mycat.config.model.TableConfig)2 RouteResultsetNode (io.mycat.route.RouteResultsetNode)2 OneRawSQLQueryResultHandler (io.mycat.sqlengine.OneRawSQLQueryResultHandler)2 SQLJob (io.mycat.sqlengine.SQLJob)2