Spring Batch Step中read_count等持续增长无回滚/跳过问题求助
Spring Batch作业read/write计数远超预期问题分析与解决
核心原因定位
你重写AbstractPagingItemReader#getPage始终返回0的逻辑,直接破坏了分页Reader的终止机制,导致作业持续读取数据无法停止:
- 原生
JpaPagingItemReader的终止逻辑是:当读取某一页返回空列表时,判定数据读取完成,返回null结束流程 - 强制
getPage返回0后,Reader每次都会重复读取第0页;而目标表持续有新数据插入,再加上JPQL的过滤/排序逻辑(比如只筛选未处理状态的记录、按创建时间倒序),导致第0页始终存在待处理数据,Reader因此无限循环读取,直到某次读取第0页为空才会终止 - 从数据也能佐证:
read_count=13395,除以pageSize=105约等于127.5,说明总共读取了128次第0页(前127次各105条,最后一次60条),这和作业运行两天的时长完全匹配
验证步骤
- 检查JPQL语句:确认是否包含类似
status = 'UNPROCESSED'的过滤条件,且Writer处理后会更新记录状态(或标记为已处理)。如果是,每次读取第0页都会拿到新的待处理数据(包括新插入的、之前未被处理的),导致持续读取 - 临时恢复原生
getPage逻辑:注释掉重写的代码,运行作业观察read_count是否等于当前符合条件的总记录数,以此验证问题根源
修复方案
根据你“避免遗漏持续插入的新数据”的需求,不推荐通过重写getPage实现,以下两种方式更合理:
方案1:定时触发一次性作业
将作业配置为定时任务(比如Spring Scheduler),定期触发单次作业:
- 每次作业读取当前所有符合条件的未处理数据
- 处理完成后作业自动终止,避免无限循环
- 逻辑简单清晰,便于监控和维护
方案2:自定义增量Reader
如果需要在单个作业内持续处理新增数据,实现增量读取逻辑:
- 记录每次读取的最大标识(比如记录ID、最新创建时间戳)
- 每次读取时,仅查询大于该标识的新记录
- 当某次读取无数据时,等待固定时长后再次查询,直到达到终止条件(比如超时、手动停止)
临时验证方案
注释掉getPage的重写代码,恢复原生分页Reader行为,运行作业后观察read_count是否与预期的总记录数一致,确认问题是否由重写逻辑导致。
补充说明
pageSize=105是单页读取条数,而非总读取上限,原生分页Reader会自动遍历所有页直到无数据rollback_count=0排除了重试导致重复读取的可能,这也解释了write_count与read_count完全相等的现象
内容的提问来源于stack exchange,提问作者Krishna Kumar Mahto
相关产品推荐
相关产品推荐

