按 create_time 倒序翻页,第一页 20 条,第二页请求带上最后一条的时间,结果少了 3 条同一秒创建的记录。日志里两条 SQL 的 where 条件一模一样。第一次遇到会往复杂处想,其实漏掉的多是个小前提。

SELECT id, create_time FROM orders
WHERE (create_time, id) < ('2026-03-01 10:00:00', 90210)
ORDER BY create_time DESC, id DESC LIMIT 20;

游标只用了 create_time,同一秒内多条记录排序不稳定,数据库返回的顺序每次可能不同。用严格大于会把同一秒剩下的记录全跳过,用大于等于又会把边界那条重复返回。这一点先确认清楚,后面就不用反复试。

「游标分页」相关的日志我一般连着看前后五分钟,单看一条报错经常判断不出是哪一步失败。

具体做法是,游标改成 create_time 加主键的联合游标 排序也按这两列;查询条件写成时间大于 或者 时间相等且主键小于;把排序字段和游标字段建一个联合索引 避免每次走文件排序;把最后一页的边界数据造出来 专门跑一遍翻页测试。

改完照着核一遍,连续翻十页 把 id 收集起来去重 总数等于第一页返回的 total 没有缺项和重复。

作者 9823189