Partial reading and writing data via Spring Batch - OutOfMemoryError: GC overhead limit exceeded
Partial reading and writing data via Spring Batch - OutOfMemoryError: GC overhead limit exceeded
我是 运行 具有 spring 批处理作业的应用程序。当我尝试从一个数据源收集一些数据并将其发布到另一个数据源时,出现以下异常。
o.s.batch.core.step.AbstractStep - Encountered an error executing step upload in job reviewsToYtBatchJob
java.lang.OutOfMemoryError: GC overhead limit exceeded
at com.mysql.jdbc.Buffer.<init>(Buffer.java:59)
at com.mysql.jdbc.MysqlIO.nextRow(MysqlIO.java:1967)
at com.mysql.jdbc.MysqlIO.readSingleRowSet(MysqlIO.java:3401)
at com.mysql.jdbc.MysqlIO.getResultSet(MysqlIO.java:483)
at com.mysql.jdbc.MysqlIO.readResultsForQueryOrUpdate(MysqlIO.java:3096)
at com.mysql.jdbc.MysqlIO.readAllResults(MysqlIO.java:2266)
at com.mysql.jdbc.ServerPreparedStatement.serverExecute(ServerPreparedStatement.java:1485)
at com.mysql.jdbc.ServerPreparedStatement.executeInternal(ServerPreparedStatement.java:856)
at com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:2318)
at com.zaxxer.hikari.pool.ProxyPreparedStatement.executeQuery(ProxyPreparedStatement.java:52)
at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.executeQuery(HikariProxyPreparedStatement.java)
at org.springframework.batch.item.database.JdbcCursorItemReader.openCursor(JdbcCursorItemReader.java:126)
我的问题是:
- 如何获取堆大小参数?
- 如何获取部分数据?
它只适用于少量数据。我也试过这个:
reader.setFetchSize(CHUNK_SIZE); //JdbcCursorItemReader
uploadStep.chunk(CHUNK_SIZE); //SimpleStepBuilder
CHUNK_SIZE 尝试了 100 到 10000 如果我将所选数据限制为有效大小,则不会超过堆大小。
protected ItemReader<Review> reader() {
JdbcCursorItemReader<Review> reader = new JdbcCursorItemReader<>();
reader.setDataSource(dataScource);
reader.setSql(
//sql query
);
reader.setFetchSize(CHUNK_SIZE);
reader.setRowMapper(
(rs, rowNum) -> new Review(
rs.getLong("reviewId"),
//map data
)
);
return reader;
}
private ItemProcessor<Review, ReviewTo> processor() {
return review -> new ReviewTo(
//parameters
);
}
private ItemWriter<ReviewTo> writer() {
return new ItemWriter<>(client);
}
private TaskletStep uploadStep() {
SimpleStepBuilder<Review, ReviewTo> uploadStep = new SimpleStepBuilder<>(stepBuilderFactory.get("upload"));
return uploadStep
.chunk(CHUNK_SIZE)
.reader(reader())
.processor(processor())
.writer(writer())
.allowStartIfComplete(true)
.build();
}
@Bean
public Job reviewsToYtBatchJob() {
return jobBuilderFactory.get(JOB_NAME)
.start(//generate table)
.build())
.next(stepBuilderFactory.get("createTmpTable")
.tasklet(//step)
.build())
.next(uploadStep())
.next(stepBuilderFactory.get("moveTmpTableToDestination")
.tasklet(//step)
.build())
.build();
}
块处理的整体思路是不将整个数据集加载到内存中,而是分块进行。因此,像您一样使用面向块的步骤是可行的方法。
How to get heap size parameter?
嗯,这个参数就是你用 -Xms
和 -Xmx
传递给 JVM 的参数。请参阅 JVM 文档中的默认值。
How fetch data partially?
当您设置面向块的步骤时,Spring Batch 会根据您步骤的块大小和JdbcCursorItemReader
的获取大小自动执行。顺便说一句,我看到你为这两个参数设置了相同的值,这是一件好事!匹配 fetchSize 和 chunkSize 通常会带来更好的性能。
所以我认为你的问题不是真正的问题,因为增加块大小时,内存中加载更多项是正常的,直到出现 OOM 错误。
内存不足space。它使用参数 CHUNK_SIZE = 100000 和 -Xmx4g。有一个带有虚拟机参数的配置文件,我可以在其中增加堆大小。
我是 运行 具有 spring 批处理作业的应用程序。当我尝试从一个数据源收集一些数据并将其发布到另一个数据源时,出现以下异常。
o.s.batch.core.step.AbstractStep - Encountered an error executing step upload in job reviewsToYtBatchJob
java.lang.OutOfMemoryError: GC overhead limit exceeded
at com.mysql.jdbc.Buffer.<init>(Buffer.java:59)
at com.mysql.jdbc.MysqlIO.nextRow(MysqlIO.java:1967)
at com.mysql.jdbc.MysqlIO.readSingleRowSet(MysqlIO.java:3401)
at com.mysql.jdbc.MysqlIO.getResultSet(MysqlIO.java:483)
at com.mysql.jdbc.MysqlIO.readResultsForQueryOrUpdate(MysqlIO.java:3096)
at com.mysql.jdbc.MysqlIO.readAllResults(MysqlIO.java:2266)
at com.mysql.jdbc.ServerPreparedStatement.serverExecute(ServerPreparedStatement.java:1485)
at com.mysql.jdbc.ServerPreparedStatement.executeInternal(ServerPreparedStatement.java:856)
at com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:2318)
at com.zaxxer.hikari.pool.ProxyPreparedStatement.executeQuery(ProxyPreparedStatement.java:52)
at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.executeQuery(HikariProxyPreparedStatement.java)
at org.springframework.batch.item.database.JdbcCursorItemReader.openCursor(JdbcCursorItemReader.java:126)
我的问题是:
- 如何获取堆大小参数?
- 如何获取部分数据?
它只适用于少量数据。我也试过这个:
reader.setFetchSize(CHUNK_SIZE); //JdbcCursorItemReader
uploadStep.chunk(CHUNK_SIZE); //SimpleStepBuilder
CHUNK_SIZE 尝试了 100 到 10000 如果我将所选数据限制为有效大小,则不会超过堆大小。
protected ItemReader<Review> reader() {
JdbcCursorItemReader<Review> reader = new JdbcCursorItemReader<>();
reader.setDataSource(dataScource);
reader.setSql(
//sql query
);
reader.setFetchSize(CHUNK_SIZE);
reader.setRowMapper(
(rs, rowNum) -> new Review(
rs.getLong("reviewId"),
//map data
)
);
return reader;
}
private ItemProcessor<Review, ReviewTo> processor() {
return review -> new ReviewTo(
//parameters
);
}
private ItemWriter<ReviewTo> writer() {
return new ItemWriter<>(client);
}
private TaskletStep uploadStep() {
SimpleStepBuilder<Review, ReviewTo> uploadStep = new SimpleStepBuilder<>(stepBuilderFactory.get("upload"));
return uploadStep
.chunk(CHUNK_SIZE)
.reader(reader())
.processor(processor())
.writer(writer())
.allowStartIfComplete(true)
.build();
}
@Bean
public Job reviewsToYtBatchJob() {
return jobBuilderFactory.get(JOB_NAME)
.start(//generate table)
.build())
.next(stepBuilderFactory.get("createTmpTable")
.tasklet(//step)
.build())
.next(uploadStep())
.next(stepBuilderFactory.get("moveTmpTableToDestination")
.tasklet(//step)
.build())
.build();
}
块处理的整体思路是不将整个数据集加载到内存中,而是分块进行。因此,像您一样使用面向块的步骤是可行的方法。
How to get heap size parameter?
嗯,这个参数就是你用 -Xms
和 -Xmx
传递给 JVM 的参数。请参阅 JVM 文档中的默认值。
How fetch data partially?
当您设置面向块的步骤时,Spring Batch 会根据您步骤的块大小和JdbcCursorItemReader
的获取大小自动执行。顺便说一句,我看到你为这两个参数设置了相同的值,这是一件好事!匹配 fetchSize 和 chunkSize 通常会带来更好的性能。
所以我认为你的问题不是真正的问题,因为增加块大小时,内存中加载更多项是正常的,直到出现 OOM 错误。
内存不足space。它使用参数 CHUNK_SIZE = 100000 和 -Xmx4g。有一个带有虚拟机参数的配置文件,我可以在其中增加堆大小。