首页 文章

处理MySQL查询耗时太长并抛出“通信链路故障”

提问于
浏览
2

我使用JDBC连接发出了一个查询:

Connection conn = null
Class.forName("com.mysql.jdbc.Driver")
conn = DriverManager.getConnection(dbHost, dbUser, dbPass)

s = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY, java.sql.ResultSet.CONCUR_READ_ONLY);
s.setFetchSize(Integer.MIN_VALUE);
r = s.executeQuery (MY_SELECT_QUERY);
while(...) { 
  processResultSet(r);
}

while 运行了很长时间来处理ResultSet . 大约1小时后我得到了例外:

com.mysql.jdbc.exceptions.jdbc4.CommunicationsException:通信链路故障从服务器成功接收的最后一个数据包是74毫秒之前 . 成功发送到服务器的最后一个数据包是4,351,980毫秒 . at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)

at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)

at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
在com.mysql.jdbc.Util.handleNewInstance(Util.java:407)
at com.mysql.jdbc.SQLError.createCommunicationsException(SQLError.java:1116)

在com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:3082)
在com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:2968)
在com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3516)
在com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:931)
在com.mysql.jdbc.MysqlIO.nextRow(MysqlIO.java:1429)
在com.mysql.jdbc.RowDataDynamic.nextRecord(RowDataDynamic.java:416)
在com.mysql.jdbc.RowDataDynamic.next(RowDataDynamic.java:395)
在com.mysql.jdbc.ResultSetImpl.next(ResultSetImpl.java:7171)
at com.busk.indexer.AbstractIndexerClient.indexResultSet(AbstractIndexerClient.scala:34)

在com.busk.indexer.ContinousIndexer.startIndexingLoop(ContinousIndexer.scala:18)

在com.busk.indexer.IndexerServer $ .main(IndexerServer.scala:95)
在com.busk.indexer.IndexerServer.main(IndexerServer.scala)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

在java.lang.reflect.Method.invoke(Method.java:597)

我已经google了,但几乎所有的错误都与连接池有关,并且使用连接的时间超过8h(默认的wait_timeout mysql设置) . 就我而言,我正处于ResultSet处理的中间,我得到了这个错误 .

1 回答

  • 1

    如果因为结果集中有大量数据而发生这种情况,我建议用“LIMIT s,m”(其中s - start和m - max记录 - 两个整数)对响应进行分页 . 然后在循环中处理此数据,一次包含1000条记录的部分:

    boolean finished = false;
    int start = 1;
    int max = 1000;
    do {
       r = s.executeQuery (MY_SELECT_QUERY + " LIMIT " + start + ", " + max);
       finished = // if r returned less than M records
       while(...) { 
         processResultSet(r);
       } 
       start += // number of returned records;
    } while (!finished);
    

    当然,1000是一个任意数字,你可以玩,找到你查询的最佳最大尺寸 .

    更新:如果每个记录的处理需要很长时间,则将记录存储在列表中,并在从数据库中提取所有数据时迭代它们 .

相关问题