解决mybatis在插入大量数据时的内存溢出问题:java.lang.OutOfMemoryError: Java heap space

分类:计算机 | 数据库 | Mybatis | 异常问题 238
更新:2021-04-24 23:29:08
编辑

异常说明

最近在项目中使用mybatis批量往mysql里面插入大量数据时总是报内存溢出的问题:java.lang.OutOfMemoryError: Java heap space。

异常分析

出现这个错误最直观的原因就是Heap size的值不够大,需要在JVM启动的时候将Heap size的值设置的大一些,但这个并不是根本可靠的解决方法,如果数据量更大的话那我们是不是得设置更大的Heap size了,谁能保证你设置的Heap size就一定够用呢,还是得从代码的角度去分析解决这个问题。

分析代码后发现有个地方存在往mysql数据库里同时插入大量数据的情况(估计有上百万条记录),从而导致内存溢出。那么既然是因为一次性插入的数据量太大了,那么可以考虑分批次插入数据,时间可能会慢一些了,但是应该可以避免内存溢出的问题了。

异常解决

上面我们分析到如果一次性插入的数据量太大的话可以考虑分批次插入数据,当然一次插入的数据量要把握好,太多了还是会内存溢出,太少的话会导致数据录入时间增加很多,所以要找一个平衡的数量,这里我选择一次插入1000条数据,改造后的代码如下:

//设备数据量较大,一次性全部插入容易引起堆内存溢出问题(java.lang.OutOfMemoryError: Java heap space)
//因此采用分批插入数据的方式
int batchCount = 1000; //每批插入数量
int batchLastIndex = batchCount;
List<Device> shareList = new ArrayList<>();
for (int index = 0; index < devices.size(); ) {
    if (batchLastIndex >= devices.size()) {
        batchLastIndex = devices.size();
        shareList = devices.subList(index, batchLastIndex);
        break;
    } else {
        shareList = devices.subList(index, batchLastIndex);
        index = batchLastIndex;// 设置下一批下标
        batchLastIndex = index + (batchCount - 1);
    }
    System.out.println("当前插入的这一批数据的索引:"+index);
    deviceExMapper.insertBatch(shareList);
}
System.out.println("最后一部分数据");
if (shareList.size()>0) {
    deviceExMapper.insertBatch(shareList);
}

这样处理以后就没有出现内存溢出的问题了。