mycat源码解读3-请求数据库

上篇讲了mycat接受到sql后是如何处理的,本篇讲mycat在接受到sql后如何数据库连接并将执行结果返回给客户端。

通过上篇我们已经知道,一个sql最终会交给NodeHandler去执行,NodeHandler会去获取一个数据库的Connection。
以MysqlConnection为例,我们看看其获取Connection部分的代码。

  • NodeHandler获取connection的方法最终走到了MysqlDataSource这个类里。MysqlDataSource通过MySQLConnectionFactory.make创建出一个Mysql连接。这里new出来的MysqlCOnnection是一个NIOSocketWR,相当于启动了一个NIOClient。打通一个MycatServer到mysql的连接。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    public MySQLConnection make(MySQLDataSource pool, ResponseHandler handler,
    String schema) throws IOException {
    DBHostConfig dsc = pool.getConfig();
    NetworkChannel channel = openSocketChannel(MycatServer.getInstance()
    .isAIO());
    MySQLConnection c = new MySQLConnection(channel, pool.isReadNode());
    MycatServer.getInstance().getConfig().setSocketParams(c, false);
    c.setHost(dsc.getIp());
    c.setPort(dsc.getPort());
    c.setUser(dsc.getUser());
    c.setPassword(dsc.getPassword());
    c.setSchema(schema);
    c.setHandler(new MySQLConnectionAuthenticator(c, handler));
    c.setPool(pool);
    c.setIdleTimeout(pool.getConfig().getIdleTimeout());
    if (channel instanceof AsynchronousSocketChannel) {
    ((AsynchronousSocketChannel) channel).connect(
    new InetSocketAddress(dsc.getIp(), dsc.getPort()), c,
    (CompletionHandler) MycatServer.getInstance()
    .getConnector());
    } else {
    ((NIOConnector) MycatServer.getInstance().getConnector())
    .postConnect(c);
    }
    return c;
    }
  • make MySQLConnection的方法调用者是PhysicDatasource.getConnection,而上篇文章提到的SingleNodeHandler和MulitNodeHandler中的execute方法都会调用该方法以获取打开数据库的连接。对db实例的具体连接是缓存的,如果有缓存则取缓存,无缓存则新建连接。

    1
    2
    PhysicalDBNode dn = conf.getDataNodes().get(node.getName());
    dn.getConnection(dn.getDatabase(), sc.isAutocommit(), node, this, node);
  • 打开连接之后,NodeHandler会调用自己的_execute方法,将处理过的请求发送给数据库。conn的responseHandler被设置成了执行sql的Handler。在我此处就是SingleNodeHandler。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    private void _execute(BackendConnection conn) {
    if (session.closed()) {
    endRunning();
    session.clearResources(true);
    return;
    }
    conn.setResponseHandler(this);
    try {
    conn.execute(node, session.getSource(), session.getSource()
    .isAutocommit());
    } catch (Exception e1) {
    executeException(conn, e1);
    return;
    }
    }

如果执行成功的话,那MysqlConnectionHandler会通过SingleNodeHandler返回OkResponse.

1
2
3
4
5
6
private void handleOkPacket(byte[] data) {
ResponseHandler respHand = responseHandler;
if (respHand != null) {
respHand.okResponse(data, source);
}
}

结果成功返回给客户端,自此一个完整的sql请求结束。