Yihui’s Blog

使用 LIMIT OFFSET 分页同步时数据丢失,原因是什么?如何解决?

日期:2026-07-12
标签:#面试 #八股 #后端 #分页 #数据同步 #场景题

一句话答案

同步期间数据新增、删除或排序字段变化会让 OFFSET 对应的逻辑位置漂移,导致重复或跳过;应使用不可变、唯一、单调游标的 Keyset Pagination,并固定快照或记录变更。

面试口语版

LIMIT 1000 OFFSET 1000 依赖“第 1001 行”的位置,但前一页数据若被删除,后续行会前移,下一页就跳过;插入或排序字段更新也会造成重复。查询若没有稳定 ORDER BY,结果顺序本身就不确定。解决方案是按主键或 (updated_at,id) 游标分页,例如 WHERE id > lastId ORDER BY id LIMIT n。全量快照期间新增/更新数据还需通过一致性快照,或记录开始位点后由 CDC 补增量,不能只靠分页解决所有并发变化。

关键细节

  • 游标字段必须唯一稳定,单用时间戳会重复。
  • 同步删除需要 CDC tombstone 或全量对账,游标查询看不到已删行。
  • 失败重启从最后已提交游标继续,Sink 仍需幂等。
  • 更新游标字段可能使记录跨页,应使用不可变主键或版本策略。

面试官追问

  1. 使用 id > lastId 会漏掉更新吗?
  2. 如何同步删除事件?
  3. 游标什么时候提交?

面试官追问参考答案

1. 使用 id > lastId 会漏掉更新吗?

它适合一次性全量扫描,但扫描过的旧 ID 后续更新不会再次出现。应在全量开始时记录 binlog 位点,扫描完成后消费增量;持续增量同步则用 CDC 或 (updated_at,id) 并处理迟到。

2. 如何同步删除事件?

物理删除只有 binlog/变更日志能可靠看到,发送带主键的 tombstone 让目标删除或标记失效。仅周期分页无法知道哪行消失,只能做昂贵全量差异对账。

3. 游标什么时候提交?

必须在该批数据成功、幂等写入目标后再原子记录 checkpoint。先提交游标再写目标会漏数;后提交可能重放,因此目标必须接受重复。

学习清单

  • 理解位置分页在动态数据上的漂移。
  • 掌握 Keyset、快照和 CDC 衔接。
Maintained by · YihuiEdit on GitHub

Keep reading

View all posts