前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >小心避坑:MySQL分页时出现的数据重复问题

小心避坑:MySQL分页时出现的数据重复问题

作者头像
SQL数据库开发
发布于 2024-04-24 09:57:30
发布于 2024-04-24 09:57:30
1.2K00
代码可运行
举报
文章被收录于专栏:SQL数据库开发SQL数据库开发
运行总次数:0
代码可运行

0 问题描述

MySQL中我们通常会采用limit来进行翻页查询,比如limit(0,10)表示列出第一页的10条数据,limit(10,10)表示列出第二页。但是,当limit遇到order by的时候,可能会出现翻到第二页的时候,竟然又出现了第一页的记录。

具体如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
SELECT
  `post_title`,
  `post_date`
FROM
  post
WHERE
  `post_status` = 'publish'
ORDER BY
  view_count desc
LIMIT
  5, 5

使用上述SQL查询的时候,很有可能出现和LIMIT 0,5相同的某条记录。而如果使用如下方式,则不会出现重复的情况:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
SELECT
  *
FROM
  post
WHERE
  post_status = 'publish'
ORDER BY
  view_count desc
LIMIT
  5, 5

但是,由于post表的字段很多,仅仅希望用这两个字段,不想把post_content也查出来。为了解决这个情况,在ORDER BY后面使用了两个排序条件来解决这个问题,如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
SELECT
  `post_title`,
  `post_date`
FROM
  post
WHERE
  `post_status` = 'publish'
ORDER BY
  view_count desc,
  ID asc
LIMIT
  5, 5

按理来说,MySQL的排序默认情况下是以主键ID作为排序条件的,也就是说,如果在view_count相等的情况下,主键ID作为默认的排序条件,不需要我们多此一举加ID asc。但是事实就是,MySQL再order by和limit混用的时候,出现了排序的混乱情况。

1 分析问题

在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版本之后才出现了这种情况。

再看下MySQL解释sql语言时的执行顺序:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
(1)     SELECT 
(2)     DISTINCT <select_list>
(3)     FROM <left_table>
(4)     <join_type> JOIN <right_table>
(5)     ON <join_condition>
(6)     WHERE <where_condition>
(7)     GROUP BY <group_by_list>
(8)     HAVING <having_condition>
(9)     ORDER BY <order_by_condition>
(10)    LIMIT <limit_number>

执行顺序依次为 form… where… select… order by… limit…,由于上述priority queue的原因,在完成select之后,所有记录是以堆排序的方法排列的,在进行order by时,仅把view_count值大的往前移动。

但由于limit的因素,排序过程中只需要保留到5条记录即可,view_count并不具备索引有序性,所以当第二页数据要展示时,mysql见到哪一条就拿哪一条,因此,当排序值相同的时候,第一次排序是随意排的,第二次再执行该sql的时候,其结果应该和第一次结果一样。

2 解决方法

1.索引排序字段

如果在字段添加上索引,就直接按照索引的有序性进行读取并分页,从而可以规避遇到的这个问题。

2.正确理解分页

分页是建立在排序的基础上,进行了数量范围分割。排序是数据库提供的功能,而分页却是衍生出来的应用需求。

在MySQL和Oracle的官方文档中提供了limit n和rownum < n的方法,但却没有明确的定义分页这个概念。

还有重要的一点,虽然上面的解决方法可以缓解用户的这个问题,但按照用户的理解,依然还有问题:比如,这个表插入比较频繁,用户查询的时候,在read-committed的隔离级别下,第一页和第二页仍然会有重合。

所以,分页一直都有这个问题,不同场景对数据分页都没有非常高的准确性要求。

3.一些常见的数据库排序问题

不加order by的时候的排序问题

用户在使用Oracle或MySQL的时候,发现MySQL总是有序的,Oracle却很混乱,这个主要是因为Oracle是堆表,MySQL是索引聚簇表的原因。所以没有order by的时候,数据库并不保证记录返回的顺序性,并且不保证每次返回都一致的。

分页问题 分页重复的问题

如前面所描述的,分页是在数据库提供的排序功能的基础上,衍生出来的应用需求,数据库并不保证分页的重复问题。

NULL值和空串问题

不同的数据库对于NULL值和空串的理解和处理是不一样的,比如Oracle NULL和NULL值是无法比较的,既不是相等也不是不相等,是未知的。而对于空串,在插入的时候,MySQL是一个字符串长度为0的空串,而Oracle则直接进行NULL值处理。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-07-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 SQL数据库开发 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
如何解决MySQL order by limit语句的分页数据重复问题?
在MySQL中我们通常会采用limit来进行翻页查询,比如limit(0,10)表示列出第一页的10条数据,limit(10,10)表示列出第二页。
JAVA葵花宝典
2021/04/08
1.4K0
mysql 5.6 order by limit 排序分页数据重复问题
https://mariadb.com/kb/en/filesort-with-small-limit-optimization/
明明如月学长
2021/08/31
1.1K0
mysql 5.6 order by limit 排序分页数据重复问题
select * from table order by xx limit 0,10
双面人
2020/02/11
1.4K0
MongoDB数据分页与排序
首先:count()总数 第一页:db.books.find().limit(3); 第二页:db.books.find().limit(3).skip(3);
字母哥博客
2020/09/23
2.2K0
Web 后端的一生之敌:分页器
分页器是 Web 开发中常见的功能,看似简单的却经常隐藏着各种奇怪的坑,堪称 WEB 后端开发的一生之敌。
Java3y
2024/03/25
1850
Web 后端的一生之敌:分页器
使用JDBC连接MySQL数据库--典型案例分析(八)----实现员工数据的分页查询
对于较大的数据量,通常采用分页查询的方式。不同的数据库产品有不同的数据库级的分页查询策略。例如:Oracle通常使用rownum的方式;而Mysql使用limit的方式。
MickyInvQ
2020/09/27
1.2K0
使用JDBC连接MySQL数据库--典型案例分析(八)----实现员工数据的分页查询
数据库-MySQL-基础(5)- DQL
注意:null 值不参与聚合函数运算(如果你查询address  出现结果为5)
莫浅子
2022/11/18
4110
数据库-MySQL-基础(5)- DQL
MYSQL中使用order by…limit时候遇到的坑
最近遇到这样的一个奇怪的问题——SQL中排序分页的查询结果中出现了重复数据。百思不得其解,检查了代码,没有发现任何问题,但这种现象就是会出现。
SEian.G
2021/03/03
1.1K0
Mysql分页order by数据错乱重复
作久项目代码优化,公司用的是Mybatis,发现分页和排序时直接传递参数占位符用的都是 $,由于$有SQL注入风险,要改为#,但是封装page类又麻烦,所以直接使用了 pageHelper 插件了,方便快捷,但是测试时发现数据有问题:
traffic
2020/04/09
2.5K0
mysql分页读取数据重复问题
服务端开发过程中,我们通常需要与mysql数据库进行数据交互。在大多数情况下,由于数据量过大、网络时延、mysql参数配置限制,以及业务逻辑的限制等,需要我们对所需的数据进行分页读取。尤其是需要读取的数据量过大时,我们经常会遇到下面这种错误类型。
闻说社
2024/12/02
2350
mysql分页读取数据重复问题
Mysql基础操作(三)
count(card) 代表只统计card字段的个数,如果有null值不会被统计。
清菡
2020/12/02
5420
Mysql基础操作(三)
MySQL 使用 order by limit 分页排序会导致数据丢失和重复!
作为程序员,经常写 SQL 语句是正常不过了。然而,编写一些 SQL 语句,总会出现一些奇怪的问题。
格姗知识圈
2021/02/02
6.5K0
MySQL 使用 order by limit 分页排序会导致数据丢失和重复!
MySQL 数据查询语言(DQL)& 事务控制语言(TCL)详解
一、 数据查询语言(DQL)(重中之重) 完整语法格式: - select 表达式1|字段,.... - from 表名 where 条件 - group by 列名 - having 条件 - order by 列名 asc|desc - limit 位置,数量 <1> 普通查询 select 查询表达式; // 最简单的sql语句,是一个函数 select database(); select version(); select now(); <2> 条件查询 wh
ruochen
2021/02/13
9550
MySQL 数据查询语言(DQL)& 事务控制语言(TCL)详解
浅谈MySQL分页查询的工作原理
MySQL 的分页查询在我们的开发过程中还是很常见的,比如一些后台管理系统,我们一般会有查询订单列表页、商品列表页等。
政采云前端团队
2023/11/09
2.1K0
浅谈MySQL分页查询的工作原理
Mysql 排序分页混乱
SELECT * FROM city order by FIELD(state,'ENABLE','DISABLE') LIMIT 0,10;
用户2146693
2021/12/28
3.6K0
Mysql 排序分页混乱
我试图扯掉这条 SQL 的底裤。只能扯一点点,不能扯多了~
好了,这次带大家盘一个我觉得有点意思的东西,也是之前写《一个烂分页,踩了三个坑!》这篇文章时,遇到的一个神奇的现象,但是当时忙着做文章搞定这个主线任务,就没有去深究这个支线任务。
why技术
2023/10/23
2240
我试图扯掉这条 SQL 的底裤。只能扯一点点,不能扯多了~
MySQL进阶学习之SQL优化【插入,主键,排序,分组,分页,计数】
如果一次性需要插入大批量数据(比如: 几百万的记录),使用insert语句插入性能较低,此时可以使用MySQL数据库提供的load指令进行插入。操作如下:
叫我阿杰好了
2022/11/07
2.3K0
MySQL进阶学习之SQL优化【插入,主键,排序,分组,分页,计数】
MySQL排序速度慢而且可能不稳定
有一个功能,按照算法得出的权重值,分页展示一批列表数据,权重值越大越靠前。研发同学反馈查询速度慢且排序不稳定。
普通程序员
2019/11/12
2.3K0
MySQL排序速度慢而且可能不稳定
Mysql基础4-数据查询
DQL全称:Data Query Language(数据查询语言),用来查询数据库中表的记录。
Se7eN_HOU
2023/07/24
2520
Mysql基础4-数据查询
java oracle分页查询语句_oracle 分页语句
SELECTOBJ_NAME, OBJ_ATTRIBUTE_NAME, ATTRIBUTE_TYPE, DES, STS, PRIORITY
全栈程序员站长
2022/09/01
1.6K0
相关推荐
如何解决MySQL order by limit语句的分页数据重复问题?
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档