使用服务器游标获取与流式传输之间的区别

ant*_*tak 5 java mysql mysql-connector

使用服务器游标获取结果和使用获取结果在行为方面有什么区别?

前者(服务器游标)可以被激活:

  • 通过设置useCursorFetch=truedefaultFetchSize=N连接属性中的每个语句。(其中N是大于零的数字。)

  • 或者单独的语句通过最初的设置useCursorFetch=truecom.mysql.jdbc.Connection.setUseCursorFetch(true)在连接上,然后是java.sql.Statement.setFetchSize(N)在语句上。

后者()可以被激活:

  • 通过设置java.sql.Statement.setFetchSize(Integer.MIN_VALUE)或调用语句在单个语句com.mysql.jdbc.Statement.enableStreamingResults()上。

  • 并且可能通过defaultFetchSize=X在连接属性中设置在每个语句上,其中X是一个等于Integer.MIN_VALUE.

使用这些替代方法进行开发时需要考虑什么? 一个好的答案可能涉及性能锁持有资源分配(/释放)等主题

nim*_*odm 3

检查Mysql的Connector/J源代码(v5.1.39):

当使用服务器游标 ( setUseCursorFetch(true)) 且结果集类型为 时TYPE_FORWARD_ONLY,“流”模式似乎只是一种特殊情况,其中获取的块仅为 1 行:

////// RowDataCursor.java /////////

private void fetchMoreRows() throws SQLException {
    ...

    synchronized (this.owner.connection.getConnectionMutex()) {
        ...

        int numRowsToFetch = this.owner.getFetchSize();
        ...

        if (numRowsToFetch == Integer.MIN_VALUE) {
            // Handle the case where the user used 'old' streaming result sets

            numRowsToFetch = 1;
        }
Run Code Online (Sandbox Code Playgroud)

另请参阅实例化的MysqlIO.java条件RowDataCursor

    //
    // Handle cursor-based fetch first
    //

    if (this.connection.versionMeetsMinimum(5, 0, 2) && this.connection.getUseCursorFetch() && isBinaryEncoded && callingStatement != null
            && callingStatement.getFetchSize() != 0 && callingStatement.getResultSetType() == ResultSet.TYPE_FORWARD_ONLY) {
        ServerPreparedStatement prepStmt = (com.mysql.jdbc.ServerPreparedStatement) callingStatement;

        boolean usingCursor = true;
Run Code Online (Sandbox Code Playgroud)

MySQL 5.7 文档指出,使用服务器游标会在服务器端生成一个临时表(如果大小允许的话,则为内存表),因此这可能会影响服务器性能。