百万级非SQL记录迁移:防遗漏、重复及崩溃恢复方案
解决方案:逐条数据迁移的防重复与崩溃恢复机制
一、防重复处理方案
针对非SQL环境,通过持久化的已处理记录索引实现重复拦截:
- 给每条迁移记录分配唯一标识:优先使用原数据库自带的唯一键(如自增ID、业务唯一ID);如果没有,提前为所有记录生成全局唯一ID(如UUID)并关联存储。
- 维护一个已成功处理记录索引文件:
- 格式可采用文本文件(每行存储一个成功记录的唯一ID),或更高效的键值对存储(如基于文件的哈希表,避免线性查询)。
- 处理任意记录前,先查询该索引:若ID已存在则直接跳过;不存在才执行后续处理流程。
二、崩溃恢复与Pending记录遗漏问题解决
核心思路是细粒度跟踪每条记录的处理状态,而非仅记录最后成功的位置,确保崩溃后能找回所有未完成的Pending记录:
1. 记录状态定义
为每条记录维护三种状态,且所有状态变更必须持久化:
待处理:尚未开始处理的记录处理中(Pending):已启动处理但未完成的记录处理成功:已完成处理并写入目标文件的记录
2. 状态持久化与处理流程
使用一个状态跟踪文件(推荐键值对格式,如记录ID:状态每行一条),并保证状态更新的原子性:
- 从数据源按顺序取出下一条
待处理记录 - 将该记录的状态更新为
处理中,写入状态文件:- 原子写入方案:先写入临时文件(如
status.tmp),写入完成后再替换正式状态文件(文件系统的rename操作是原子的,避免崩溃导致状态文件损坏)
- 原子写入方案:先写入临时文件(如
- 执行数据处理与目标文件写入操作:
- 写入目标文件时同样保证原子性:单条记录先写入临时文件,确认写入完成后追加到最终目标文件
- 处理成功后:
- 将该记录状态更新为
处理成功,原子写入状态文件 - 将记录ID添加到已成功处理索引文件中
- 将该记录状态更新为
- 若处理失败(如异常中断):
- 将状态更新为
处理失败,后续可触发重试逻辑
- 将状态更新为
3. 崩溃恢复流程
程序重启时,按以下步骤恢复:
- 读取状态跟踪文件,筛选出所有状态为
处理中的记录——这些就是崩溃前未完成的Pending记录 - 优先重新处理所有
处理中的记录,按原顺序执行完整处理流程,直到状态更新为处理成功 - 扫描已成功处理索引文件,找到最大的已成功记录ID,作为后续新记录处理的起点
- 继续按顺序处理后续
待处理的记录,同时监听新增记录
针对示例场景的修复效果
原示例中,Record4、5标记为处理中,Record6标记为处理成功。程序崩溃重启后:
- 首先识别出Record4、5为未完成的Pending记录,重新处理并更新状态为
处理成功 - 之后从Record7(若存在)开始处理新记录,完全避免遗漏问题
三、性能优化建议
- 对于430万条数据,文本格式的索引文件查询效率较低,可采用排序后的ID索引(按ID升序存储),通过二分查找快速判断记录是否已处理
- 状态文件和索引文件可采用批量写入优化(如每处理100条记录批量更新一次),但需注意:批量内的记录若崩溃需全部重新处理,需在性能和可靠性间做平衡
- 若数据源支持按ID范围查询,可结合已成功的最大ID快速定位下一批待处理记录,避免全量扫描
内容的提问来源于stack exchange,提问作者Calvin Lee
相关产品推荐
相关产品推荐

