• MySQL的JDBC OutOfMemoryError: Java heap space异常


    MySQL的JDBC OutOfMemoryError: Java heap space异常

            MySql数据库通过JDBC对大表进行查询时抛出java.lang.OutOfMemoryError: Java heap space异常。这是因为默认情况下,MySQL的JDBC驱动会一下子把所有row都读取下来,这在一般情况下是最优的,因为可以减少Client-Server的通信开销。但是这样也有一个问题,当数据库查询结果很大时,特别当不能全部放进内存时,就会产生性能问题。

    本来,JDBC api里在Connection、Statement和ResultSet上都有设置fetchSize的方法,但是MySQL的JDBC驱动都不支持,无论你怎么设fetchSize,ResultSet都会一次性从Server读取数据。在MySQL的官方论坛上也有多个这样的问题,总结一下解决办法如下:

    1.MySQL版本在5.0以上,MySQL的JDBC驱动更新到最新版本(至少5.0以上)
    2.Statement一定是TYPE_FORWARD_ONLY的,并发级别是CONCUR_READ_ONLY(即创建Statement的默认参数)
    3.以下两句语句选一即可:
        1).statement.setFetchSize(Integer.MIN_VALUE);
        2).((com.mysql.jdbc.Statement)stat).enableStreamingResults();

    这样会一行一行地从Server读取数据,因此通信开销很大,但内存问题可以解决。官方的说法是不支持fetchSize不是MySQL的JDBC驱动的问题,而是MySQL本身就不支持。而商用数据库Oracle或DB2都是支持fetchSize的,从这里也可以看出两者的考量不同。

    考虑到应用程序利用JDBC跨数据库的特性可以,通过判断mySql连接特殊处理:

                    if(conn.getClass().getName().indexOf("mysql")>0){

                     //com.mysql.jdbc.Driver
                      stmt.setFetchSize(Integer.MIN_VALUE); 
                    }

    开始以为是自己的代码有问题,找了半天没找到。后来仔细看了异常才发现:

    严重: Servlet.service() for servlet ExportServlet threw exception
    java.lang.OutOfMemoryError: Java heap space

    at com.mysql.jdbc.Buffer.getBytes(Buffer.java:198)

    at com.mysql.jdbc.Buffer.readLenByteArray(Buffer.java:318)
    at com.mysql.jdbc.MysqlIO.nextRow(MysqlIO.java:1366)
    at com.mysql.jdbc.MysqlIO.readSingleRowSet(MysqlIO.java:2333)
    at com.mysql.jdbc.MysqlIO.getResultSet(MysqlIO.java:435)
    at com.mysql.jdbc.MysqlIO.readResultsForQueryOrUpdate(MysqlIO.java:2040)
    at com.mysql.jdbc.MysqlIO.readAllResults(MysqlIO.java:1443)
    at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:1777)
    at com.mysql.jdbc.Connection.execSQL(Connection.java:3249)
    at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1268)
    at com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:1403)
    at com.mchange.v2.c3p0.impl.NewProxyPreparedStatement.executeQuery(NewProxyPreparedStatement.java:76)
    at com.cdnlog.servlet.ExportServlet.doPost(ExportServlet.java:77)

    ExportServlet.java:77,代码这里是rs=pstmt.executeQuery();

    这句话报错。然后求助网友鬼精灵,找到如上那篇文章。解决了~

    谢谢鬼精灵~,哈哈,也许你看不到


  • 相关阅读:
    广播接收者的生命周期?
    如何让自己的广播只让指定的 app 接收?
    在 manifest 和代码中如何注册和使用 BroadcastReceiver?
    请描述一下 BroadcastReceiver?
    说说 Activity、Intent、Service 是什么关系
    什么是IntentService?有何优点?
    Activity 怎么和 Service 绑定,怎么在 Activity 中启动自己对应的 Service?
    Service 是否在 main thread 中执行, service 里面是否能执行耗时的操作?
    两个 Activity 之间跳转时必然会执行的是哪几个方法?
    如何保存 Activity 的状态?
  • 原文地址:https://www.cnblogs.com/miraclespace/p/3712397.html
Copyright © 2020-2023  润新知