Java批量数据库并行导入关键在于合理分片(200~500条/批)、线程池与连接池协同(如HikariCP=20时线程数设12~16)、每批独占连接、批量SQL+幂等重试,禁用共享Connection和CachedThreadPool。

Java 中批量数据库操作结合线程池实现并行导入,关键不是“多开线程”,而是合理分片、资源隔离、连接独占和错误可控。盲目增加线程数反而引发连接争用、锁等待甚至事务回滚。
按批次切分数据(200~500 条/批)
大列表直接丢给线程池会内存溢出或拖慢单个任务。需预先拆成小批次:
- 用 List.subList(start, Math.min(start + batchSize, list.size())) 安全截取,避免越界
- 推荐每批 200~500 条:太小则 SQL 开销占比高;太大易触发行锁或超时
- 工具方法建议泛型化,如 split(List
data, int size) 返回 List- >
配置匹配的固定线程池(8~16 线程)
线程数必须与数据库连接池上限协同设计,否则大量线程卡在获取连接上:
- 若 HikariCP 的 maximum-pool-size = 20,线程池设为 12~16 更稳妥
- 避免用 Executors.newCachedThreadPool() —— 无界线程可能压垮系统
- 推荐 newFixedThreadPool(n) 或自定义 ThreadPoolExecutor,设置有界队列和拒绝策略
每批任务独占数据库连接
多个线程共用一个 Connection 或 SqlSession 是并发安全的大忌:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
立即学习“Java免费学习笔记(深入)”;
- Spring 环境下,确保每个 Runnable 在 @Transactional 方法内执行,或通过 TransactionTemplate 控制事务边界
- 纯 JDBC 场景:在线程任务内部调用 dataSource.getConnection(),操作完立即 close()
- MyBatis-Plus 可复用 Mapper 接口实例,但不能跨线程共享未提交的 SqlSession 或手动管理的 Connection
用批量 SQL + 幂等重试兜底
单条 INSERT/UPDATE 在并发下极易冲突,必须从语句和逻辑两层防护:
- INSERT 使用 INSERT INTO ... VALUES (),(),()... 批量语法,比循环快 5~10 倍
- UPDATE 若按非主键条件更新,考虑先 SELECT FOR UPDATE SKIP LOCKED 预占记录,防重复处理
- 每批任务用 try-catch 包裹,失败时记录日志 + 保存原始数据(如写入 error_log 表),支持人工或自动重试
- 主键避免用 UUID.randomUUID() 多线程并发生成,改用雪花 ID 或 DB 序列预分配段
主线程需确认全部完成:用 CountDownLatch 或 CompletableFuture.allOf() 等待所有批次返回,再统一汇总结果或抛异常。

















