MySQL JDBC的局限性

时间:2013-03-20 07:10:45

标签: java mysql spring jdbc driver

问题:

我从DB(MySQL)获得大型ResultSet(超过1 000 000行)并处理每行大约40秒。 总结,我使用ResultSet超过30分钟,我得到的记录少于数据库表中真正包含的记录,没有错误,也没有任何保证。如果我计算该ResultSet的行数,它就没事了(ResultSet的数量= DB的数量)。

mysql服务器或mysql jdbc驱动程序有什么限制吗?

我的代码。它适用于spring框架:

 public void query(String query, RowCallbackHandler rowCallbackHandler) throws SQLException {
    ResultSet rs = null;
    ResultSet rsCount = null;
    Statement stmt = null;
    Statement stmtCount = null;
    try {
        stmt = createStatmant();

        rs = stmt.executeQuery(query);

        if (rs == null) {
            log.info("result set is null");
        }

        stmtCount = createStatmant();
        rsCount = stmtCount.executeQuery(query);
        int i = 0;
        while(rsCount.next()){
            i++;
        }
        log.info("ResultSet size : "+i);

        int j = 0;
        rs.next();
        do{
            j++;
            rowCallbackHandler.processRow(rs);
        }while (rs.next());
        log.info("ResultSet size real : "+i);
        log.info("ResultSet size fact : "+j);
    } catch (SQLException e) {
        throw new RuntimeException(e.getMessage());
    }finally{
        if(stmt!=null){
            stmt.close();
        }
        if(rs!=null){
            rs.close();
        }
        if(rsCount!=null){
            rsCount.close();
        }
    }
  }

createStatment:

  private Statement createStatmant() throws SQLException {

    ((BasicDataSource)dataSource).setTimeBetweenEvictionRunsMillis(1000*60*60);
    Statement stmt = dataSource.getConnection().createStatement(
            ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
    stmt.setFetchSize(fetchSize);
    stmt.setMaxRows(50000000-1);    
    return stmt;
}    

datasource是类中的全局变量:

    private javax.sql.DataSource dataSource;

1 个答案:

答案 0 :(得分:0)

你正在将一个可变对象rs传递给你的callbackHandler。确保它没有提前或关闭ResultSet。

您声明了四个可以在方法顶部关闭的对象,但只在底部关闭了三个。不要忘记关闭stmtCount。

我假设您将这一点作为我们利益的故障排除方法,并且您不会在生产中这样做。

1百万行乘以40秒= 40百万秒= 463天。数学不支持你“处理每行大约40秒”的陈述。

在您阅读时,是否有任何外部写入数据库的内容?

如果您能够比较日志中的计数,则表示您没有抛出异常。这是一个有用的线索。