java大批量数据导入分批提交的核心是控制单次处理量与资源占用,关键在每批大小(500~5000行)、资源及时释放(executebatch+clearbatch)、事务边界设置(按批提交+断点续传)及流式读取防oom。

Java 中大批量数据导入时,分批提交的核心是控制单次处理的数据量和资源占用,避免一次性加载全部数据到内存或堆积过多未提交的 JDBC 批次。关键不在“分多少批”,而在于“每批多大”+“如何释放资源”+“事务边界怎么设”。
合理设置批次大小(batchSize)
批次大小不是越大越好,也不是越小越稳,需结合数据行体积、JVM 堆内存、数据库连接限制和事务日志压力综合判断。常见经验范围是 500~5000 行/批:
- 单行数据较简单(如纯数字、短字符串),可设 2000~5000;
- 含大字段(BLOB/CLOB)、JSON 字符串或关联校验逻辑,建议 500~1000;
- 使用 MyBatis 时,务必关闭 autoCommit 并显式调用 sqlSession.flushStatements(),否则 batch 模式可能退化为逐条执行;
- JDBC 层(如 PreparedStatement.addBatch())需在每批后调用 executeBatch() + clearBatch(),否则 BatchCommand 缓存持续增长,引发 OOM。
流式读取 + 边读边处理
避免把整个 Excel/CSV/JSON 文件一次性解析成 List
- 读 CSV:用 OpenCSV 的
CsvToBeanBuilder配合RowProcessor,或 Apache Commons CSV 的Iterable<csvrecord></csvrecord>; - 读 Excel:用 Apache POI 的
SAX 模式(XSSFSheetXMLHandler)或 EasyExcel 的AnalysisEventListener,不加载全表到内存; - 读数据库导出文件:优先走游标分页(如 MySQL 的
SELECT ... LIMIT offset, size或更优的基于主键的游标分页),而非 OFFSET 跳跃式分页。
事务粒度与异常恢复设计
不要把几万条数据包在一个事务里提交——失败则全部回滚,重试成本高,且长事务易锁表、占 undo log:
- 按批次提交事务(例如每 1000 条 commit 一次),用 Spring 的
@Transactional(propagation = Propagation.REQUIRES_NEW)隔离每批; - 记录已成功处理的最小 ID 或时间戳,支持断点续传(尤其定时任务场景);
- 捕获 SQLException 或 DataAccessException 后,打印当前批次起始位置并跳过该批(或降级为单条重试),避免因某条脏数据阻塞全局流程。
监控与兜底机制
生产环境必须有可见性,不能只靠“跑完没报错”来判断成功:
- 每批处理前后打印日志,含批次序号、起始 ID、行数、耗时、GC 状态(如
ManagementFactory.getMemoryMXBean().getHeapMemoryUsage()); - 设置 JVM 参数如
-XX:+PrintGCDetails -Xlog:gc*:file=gc.log,观察是否频繁 Full GC; - 对超大导入任务(如 >100 万行),加内存阈值检查:若堆使用率连续 3 次 >85%,主动触发批次缩小(如从 2000 → 500)或暂停 1 秒让 GC 回收。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











