AI优化批量任务后为什么数据开始重复或漏处理?分页、游标与并发消费解析
AI帮我们优化批量任务时,经常会做一件看起来很合理的事:
把原来一条一条处理,改成分页、批量甚至并发执行。
速度确实变快了,但随后可能出现另一类很隐蔽的问题:
- 明明任务全部跑完,最终数量却对不上;
- 某些数据处理了两次;
- 有些记录完全没被处理;
- 第一次运行正常,第二次结果又不同;
- 并发数越高,重复和遗漏越明显;
- 日志没有明显报错,但业务数据就是少了一部分。
这类问题的危险之处在于:
任务“执行完成”并不代表每条数据都被正确处理了一次。
一、最常见的问题是分页过程中数据本身还在变化
假设AI把任务改成:
每次查询100条,处理完以后继续下一页。
如果使用 LIMIT + OFFSET:
第一页读取第1~100条,第二页再读取第101~200条。
看起来没有问题。
但如果第一批处理过程中,某些数据状态被修改,已经不再满足原来的查询条件,剩余数据的位置就可能发生变化。
例如原本有300条“待处理”数据。
第一批处理100条以后,这100条状态变成“已完成”,从查询结果中消失。
这时候再执行:
OFFSET 100
实际上可能直接跳过新的前100条。
结果就是:
任务没有报错,但中间一批数据被漏掉了。
二、一边分页,一边修改查询条件特别危险
很多批处理都会使用类似条件:
查询 status = pending 的记录。
处理完成后,再把它改成:
status = done。
这意味着数据集本身一直在缩小。
如果继续使用固定Offset翻页,相当于:
一边改变队伍顺序,一边按照旧位置继续往后数。
所以这类任务里,代码表面完全正确,分页SQL也没有语法问题,但最终结果仍然可能缺数据。
三、没有稳定排序,也可能导致分页结果漂移
即使数据没有被删除,如果查询没有明确稳定排序,也可能出问题。
例如只写:
查询100条记录。
数据库并不保证每次都按照完全一样的顺序返回。
第一页里出现过的数据,下一次查询时可能因为执行计划、数据变化等原因跑到另一页。
如果任务依赖分页边界,就可能出现:
同一条记录重复出现,或者某条记录被跨页跳过。
所以批量处理最好保证有明确、稳定的排序字段。
例如:
按唯一ID递增处理。
四、Cursor为什么通常比Offset更适合持续批处理
相比一直使用:
OFFSET 100、OFFSET 200、OFFSET 300
更稳定的一种思路是记录:
上一批最后处理到哪个ID。
例如第一批处理到:
id = 1050
下一批直接查询:
id > 1050,继续取100条。
这种方式的核心不是“第几页”,而是:
上一次处理到了哪里。
即使前面的数据状态发生变化,也不会因为结果集缩小而把后面的记录整体向前移动。
这就是为什么很多长期运行的批处理更适合基于:
Cursor、主键或稳定游标
继续推进。
五、并发消费又会引入另一类重复问题
AI为了进一步提升速度,可能把一个Worker改成多个Worker同时处理。
例如:
Worker A查询一批待处理任务。
Worker B同时也查询一批待处理任务。
如果两边查询发生得很接近,就可能同时拿到同一条记录。
结果:
A处理一次,B又处理一次。
如果这个任务只是生成报表,可能影响不大。
但如果涉及:
- 扣库存;
- 发优惠券;
- 发短信;
- 创建订单;
- 调第三方接口;
重复消费就可能直接造成业务事故。
六、“先查出来再改状态”也存在时间窗口
例如流程是:
查询 pending → 执行业务 → 更新为 done
两个Worker可能同时在“更新为done”之前读到同一条任务。
所以并发环境下,仅仅依赖:
我处理完以后会改状态。
并不能保证任务只执行一次。
更稳的方式通常要考虑:
- 原子抢占;
- 状态条件更新;
- 唯一约束;
- 分布式锁;
- 队列消费确认;
- 幂等处理。
核心目标是:
同一条任务不能同时被多个Worker认为“属于自己”。
七、为什么测试很容易发现不了?
普通测试往往只有:
- 少量数据;
- 单Worker;
- 数据不会实时变化;
- 一次执行完成就结束。
这和生产环境差别很大。
真正上线以后,可能同时存在:
- 新数据不断插入;
- 旧数据持续更新;
- 多个Worker抢任务;
- 任务失败重试;
- 数据库响应时间变化。
于是原本在测试环境非常稳定的分页逻辑,到了生产环境才开始重复或漏数据。
所以批量任务不能只测试:
能不能跑完。
还要检查:
处理数量、唯一性和完整性。
八、怎么检查有没有重复或遗漏?
最直接的方法不是只看:
Job completed successfully。
而是增加结果校验。
例如记录:
- 本次扫描总数;
- 实际处理总数;
- 成功数量;
- 失败数量;
- 唯一ID数量;
- 重复ID数量;
- 未处理剩余数量。
如果:
处理次数 = 10000
但:
唯一ID只有9800
那就说明存在重复。
如果理论应该处理10000条,最终只有9600条进入完成状态,就要继续排查遗漏。
批量任务真正需要的是:
结果对账。
九、AI优化批处理后,最好做一次完整性检查
以后让AI优化批量任务,可以明确要求:
请检查当前分页是否会因为处理过程中数据状态变化导致Offset漂移;确认排序是否稳定;评估是否应该改成基于ID或Cursor继续处理;如果存在多Worker并发,请检查任务抢占、重复消费和幂等性。最后增加处理总数、唯一ID数、失败数和剩余数校验。
这样AI关注的就不只是:
任务快了多少。
还会进一步检查:
每条数据是不是恰好处理一次。
最后
AI优化批量任务后出现数据重复或漏处理,本质上通常不是:
循环写错了。
而是:
数据集在变化,而分页和并发策略仍然假设它是静态的。
Offset分页可能因为数据移动而跳过记录,并发Worker可能因为抢占不完整而重复处理。
所以真正稳定的批任务,需要同时考虑:
稳定排序、Cursor推进、任务抢占、幂等性和结果对账。
批处理真正的正确标准不是:
任务有没有跑完。
而是:
所有应该处理的数据,是否都被准确处理,而且没有重复。
持续更新 Codex、AI编程与后端工程实战内容,更多深度内容和稳定订阅渠道欢迎搜索关注「孤狼GPT」。
更多推荐



所有评论(0)