美文网首页
Limit 分页的一个bug

Limit 分页的一个bug

作者: 蓉漂里的小白 | 来源:发表于2023-05-27 14:10 被阅读0次

问题描述

今天遇到了一个bug, 非常奇怪,实习生用代码了一个limit 的分页,定时任务执行时候发现每次都会丢一半的数据。
仔细查看了日志发现共有18页,但是从第10页开始每次查询到的数据都是0条 ???
哈哈哈,有点蒙

原因分析

然后仔细梳理了一下业务逻辑发现了,原来犯了如此低级的一个错误, 😭😭😭

业务逻辑:
起一个定时任务,消费100条数据,采用分页每次读取50条,消费成功后更新数据状态,然后再取下一页
因为生产环境数据量太大,所以在本机造了20条数据,每次读4条 进行测试
代码运行分析如下:
第一轮

//查询总数
SELECT COUNT(1) from students s2 

//for 循环分页查询 
 select * from students s where s.sInt_10 = 0 order by s.sId ASC LIMIT 0, 4 
<结果返回的是sID包含:1,2,3,4>

//消费完成更新数据状态
UPDATE students set sInt_10 = 1 where sId in (1,2,3,4)

第二轮

select * from students s where s.sInt_10 = 0 order by s.sId ASC LIMIT 4, 4
<结果返回的是sID包含:9,10,11,12>

image.png
//消费完成更新数据状态
UPDATE students set sInt_10 = 1 where sId in (9,10,11,12)

到这里发现问题了,居然返回的是9,10,11,12 而不是5,6,7,8; 说明原本设想的第2页数据被跳过了;
忽然反应过来了,因为我们加了where 条件导致第一次更新了1,2,3,4的状态后,第二次再查询只是查了1,2,3,4之外的数据,但是我们的limit 又改变了offset; 所以导致第二次查询丢1页(5,6,7,8);第三次查询丢2页(5,6,7,8; 13,14,15,16)

解决方案

每次都读4条,一直到读取不到数据为止
第二次查询

select * from students s where s.sInt_10 = 0 order by s.sId ASC LIMIT 0, 4
image.png

更新第二次查询到的数据状态

UPDATE students set sInt_10 = 1 where sId in (5,6,7,8)

第三次查询

select * from students s where s.sInt_10 = 0 order by s.sId ASC LIMIT 0, 4
image.png

更新第三次查询到的数据状态

UPDATE students set sInt_10 = 1 where sId in (13,14,15,16)

这样就一切正常了

总结

其实这个分页问题是一个很基础的问题,但是这次踩坑是因为实际项目中大家都很少写sql了。中型公司有ORM,大型公司有专业DBA,程序员只需要RPC 走微服务就好了;
所以基础知识还是很重要

相关文章

网友评论

      本文标题:Limit 分页的一个bug

      本文链接:https://www.haomeiwen.com/subject/nonledtx.html