Mycat1.6事务问题

    使用Mycat用于读写分离时,对数据库的事务不跨库,如果硬要打开事务没有关闭的话,容易产生系统事务紊乱等问题。通过源代码仔细分析,发现mycat并非透传sql语句。

   start transaction的处理

public final class StartHandler {

    private static final byte[] AC_OFF = new byte[] { 7, 0, 0, 1, 0, 0, 0, 0,

            0, 0, 0 };

    public static void handle(String stmt, ServerConnection c, int offset) {

        switch (ServerParseStart.parse(stmt, offset)) {

        case ServerParseStart.TRANSACTION:

            if (c.isAutocommit())

            {

                c.setAutocommit(false);

                c.write(c.writeToBuffer(AC_OFF, c.allocate()));

            }else

            {

                c.getSession2().commit() ;

            }

            break;

        default:

            c.execute(stmt, ServerParse.START);

        }

    }

}

也就是说,mycat把start transaction 改成了set commit=0,而且不是立即发送给后端mysql

2019-11-19T01:43:01.970695Z     5 Query SET autocommit=0;

2019-11-19T01:43:01.970695Z     5 Query update city set Name='MJMJ' where id=1

2019-11-19T01:43:06.907978Z     5 Query commit

2019-11-19T01:43:06.953980Z     5 Query rollback

2019-11-19T01:43:19.846718Z     5 Query SET autocommit=1;

2019-11-19T01:43:19.846718Z     5 Query select * from city where id = 1

前两条是一起送给mysql的。如果事务没有关闭,导致整个连接的autocommit属性的改变。

多了一个rollback

从上面一个简单的事务,可以发现每次commit后面都会跟着一个rollback

通过分析源代码NoBlockingSession.java发现

public void releaseConnection(RouteResultsetNode rrn, boolean debug, final boolean needRollback) {

BackendConnection c = target.remove(rrn);

if (c != null) {

if (debug) {

LOGGER.debug("release connection " + c);

}

if (c.getAttachment() != null) {

c.setAttachment(null);

}

if (!c.isClosedOrQuit()) {

if (c.isAutocommit()) {

c.release();

} //else if (needRollback) {

c.setResponseHandler(new RollbackReleaseHandler());

c.rollback();

} //else {

c.release();

}

}

}

}

needRollback的判断竟然被注释掉了,实在令人费解啊!

至此,mycat单node简单事务问题终于研究清楚了。

你可能感兴趣的:(Mycat1.6事务问题)