MySQL分页时使用 limit+order by 会出现数据重复问题

  • 内容
  • 评论
  • 相关

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();


本文标签:

版权声明:若无特殊注明,本文皆为《菜鸟站长》原创,转载请保留文章出处。

本文链接:MySQL分页时使用 limit+order by 会出现数据重复问题 - http://wlphp.com/?post=333

发表评论

电子邮件地址不会被公开。 必填项已用*标注