返回

记录因Sharding Jdbc批量操作引发的一次fullGC

后端

一、背景

我们有一个使用Sharding Jdbc管理数据库分库分表的项目,最近在进行压力测试时,发现项目在进行大批量数据插入操作时,会出现fullGC的问题。为了解决这个问题,我们对GC日志进行了分析,并总结了经验教训。

二、问题复现

为了复现问题,我们在本地环境中搭建了一个模拟项目。项目使用Spring Boot框架,数据库使用MySQL。分表策略是使用Sharding Jdbc的RangeShardingAlgorithm,对ID字段进行分片。

我们使用以下代码进行批量插入操作:

List<User> users = new ArrayList<>();
for (int i = 0; i < 100000; i++) {
    User user = new User();
    user.setId(i);
    user.setName("user" + i);
    users.add(user);
}

jdbcTemplate.batchUpdate("insert into user (id, name) values (?, ?)", users);

在运行这段代码时,我们发现项目在插入大约10万条数据后,会出现fullGC的问题。

三、GC日志分析

为了分析GC日志,我们使用MAT工具打开了堆内存快照。

在堆内存快照中,我们发现有一个名为"byte[]"的数组占据了大量的内存空间。这个数组是Sharding Jdbc用于批量操作的临时缓冲区。

当Sharding Jdbc进行批量操作时,它会将数据先缓存到这个临时缓冲区中,然后一次性将所有数据插入到数据库中。

如果批量操作的数据量过大,那么这个临时缓冲区就会占用大量的内存空间,从而导致fullGC的发生。

四、解决方案

为了解决这个问题,我们可以通过以下两种方式来减少临时缓冲区占用的内存空间:

  • 减少批量操作的数据量。
  • 增大临时缓冲区的容量。

在我们的项目中,我们通过减少批量操作的数据量来解决了这个问题。我们将批量操作的数据量从10万条减少到1万条,这样就不会导致fullGC的发生了。

五、经验教训

通过这次事件,我们总结了以下经验教训:

  • 在使用Sharding Jdbc进行批量操作时,要控制好批量操作的数据量,以避免导致fullGC的发生。
  • 在使用Sharding Jdbc进行批量操作时,可以适当增大临时缓冲区的容量,以减少临时缓冲区占用的内存空间。
  • 在进行压力测试时,要模拟真实的业务场景,以避免出现意外情况。

六、结语

以上就是我们记录因Sharding Jdbc批量操作引发的一次fullGC的经验教训。希望对大家有所帮助。