您好,欢迎访问一九零五行业门户网

MySQL的JDBC OutOfMemoryError: Java heap space异常

mysql的jdbc outofmemoryerror: java heap space异常 http://hi.baidu.com/tlw_ray/blog/item/ab925bf4ff3312d1f3d385e2.html mysql数据库通过jdbc对大表进行查询时抛出java.lang.outofmemoryerror: java heap space异常。这是因为默认情况下,mysql的jdbc驱
mysql的jdbc outofmemoryerror: java heap space异常
http://hi.baidu.com/tlw_ray/blog/item/ab925bf4ff3312d1f3d385e2.html
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();
这句话报错。然后求助网友鬼精灵,找到如上那篇文章。解决了~
谢谢鬼精灵~,哈哈,也许你看不到
其它类似信息

推荐信息