PHP菜鸟博客_共同学习分享PHP技术心得【PHP爱好者】
MySQL分页时使用 limit+order by 会出现数据重复问题
2022-3-18 菜鸟站长


1.先说下现象在第一个页里面出现了"三只松鼠",然后在第二页里面还有“三只松鼠”



第一页sql:





SELECT * FROM `client_good_classifylist` WHERE  (  1=1  and  clientkeynum='83D965C149CC5C9BA793896B389E8FBD' and is_del=1  ) ORDER BY `o` ASC LIMIT 0,10



1.jpg



第二页sql:



SELECT * FROM `client_good_classifylist` WHERE  (  1=1  and  clientkeynum='83D965C149CC5C9BA793896B389E8FBD' and is_del=1  ) ORDER BY `o` ASC LIMIT 10,10



2.jpg



排序号字段o是int类型,当排序号o的值都是一样的,我的数据都是0的时候,出现了这样的情况。







2.问题分析



在MySQL 5.6的版本上,优化器在遇到order by limit语句的时候,做了一个优化,即 使用了priority queue。

使用 priority queue 的目的,就是在不能使用索引有序性的时候,如果要排序,并且使用了limit n,那么只需要在排序的过程中,保留n条记录即可,这样虽然不能解决所有记录都需要排序的开销,但是只需要 sort buffer 少量的内存就可以完成排序。

之所以MySQL 5.6出现了第二页数据重复的问题,是因为 priority queue 使用了堆排序的排序方法,而堆排序是一个不稳定的排序方法,也就是相同的值可能排序出来的结果和读出来的数据顺序不一致。

MySQL 5.5 没有这个优化,所以也就不会出现这个问题。

也就是说,MySQL 5.5是不存在本文提到的问题的,5.6版本之后才出现了这种情况。



3.解决办法



后面加一个辅助排序字段,形成排序组合,为了保证辅助字段值不重复我使用自增id。







        $list = Db::table('client_good_classifylist')

            ->where($where)

            ->order("o", "asc")

            ->order("id", "desc")

            ->limit($offset . ',' . $pagesize)

            ->select();





发表评论:
昵称

邮件地址 (选填)

个人主页 (选填)

内容