MySQL分页查询limit踩坑记
1 问题背景
线上有一个批处理任务,会批量读取昨日的数据,经过一系列加工后,插入到今日的表中。表结构如下:
1 CREATE TABLE `detail_yyyyMMdd` (
2 `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
3 `batch_no` varchar(64) NOT NULL COMMENT '批次号',
4 `order_id` varchar(64) NOT NULL COMMENT '订单ID',
5 `user_id` varchar(64) NOT NULL COMMENT '用户ID',
6 `status` varchar(4) NOT NULL COMMENT '状态',
7 `product_id` varchar(32) NOT NULL COMMENT '产品ID',
8 PRIMARY KEY (`id`),
9 KEY `idx_batchno_userid` (`batch_no`,`user_id`)
10 ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='明细表';
因数据量较大,批量读取昨日数据时,使用了分页查询limit语句,查询sql如下:
SELECT id,batch_no,order_id,user_id,status,product_id FROM detail_yyyyMMdd WHERE batch_no=‘batch_type_yyyyMMdd’ LIMIT ?,?;
从某一天开始,客服频繁收到客诉,反馈数据未更新。
2 问题排查
初步排查,客诉反馈的数据确实没有插入。线上增加了一些业务日志后,发现分页查询昨日数据时,第二次查询的结果集与第一次查询的结果集有重复数据。
与DBA沟通,确认了客诉爆发前一天做了一次数据库变更,兄弟团队为了解决一个慢查询问题,增加了一个索引,变更sql如下:
ALTER TABLE `detail_yyyyMMdd` ADD INDEX `idx_batchno_status_productid` (`batch_no`, `status`, `product_id`);
DBA分析,该变更sql上线前,分页查询会走idx_batchno_userid索引,上线后则走idx_batchno_status_productid,而该索引存在大量重复记录,导致每次分页查询的数据都可能和之前的重复。
为什么索引有重复记录时,分页查询的数据就可能与之前的重复呢?在网上搜了下,这里贴一篇官方的文档:https://dev.mysql.com/doc/refman/5.6/en/limit-optimization.html
If multiple rows have identical values in the ORDER BY columns, the server is free to return those rows in any order, and may do so differently depending on the overall execution plan. In other words, the sort order of those rows is nondeterministic with respect to the nonordered columns.
One factor that affects the execution plan is LIMIT, so an ORDER BY query with and without LIMIT may return rows in different orders.
If it is important to ensure the same row order with and without LIMIT, include additional columns in the ORDER BY clause to make the order deterministic.
在MySQL 5.6的版本上,优化器在遇到order by limit语句时,做了个查询优化,即使用了priority queue(优先级队列)。采用priority queue能够根据limit N维护一个大小为N的堆,在排序的过程中,只用保留N条记录即可。但堆排序是一个不稳定的排序算法,所以当排序字段值存在重复时,返回的数据顺序可能会不一样,其中一个影响因素就是limit。
解决方案:查询语句加上order by id(保证排序字段的唯一性),上线后,问题得到解决。
但仍然存在两个疑点:
原来的索引idx_batchno_userid也会有重复记录,为什么一直没有爆出问题?
线上的查询语句只有limit,没有order by,可以直接按照索引的有序性(索引聚簇表)进行读取并分页,不需要触发priority queue优化。
3 问题定位
仔细观察了两次分页查询的结果集后发现,两次结果集的数据顺序分别对应两个索引,即第一次分页查询走了索引idx_batchno_userid,第二次分页查询走了索引idx_batchno_status_productid,两个索引的数据顺序是不一样的,从而导致两次分页查询的数据存在重复。与DBA交流,MySQL的优化器会基于成本选择最优的索引,而这两个索引的成本相差不大。
这个结论在线下得到复现,但并不能稳定复现。在总结果集没有变化的情况下,两次分页查询分别走了不同索引的根因,还有待继续深挖。
End
MySQL使用limit进行分页查询时,可能会出现重复数据,可以通过加上order by子句并保证排序字段的唯一性来解决。

MySQL分页查询limit踩坑记的更多相关文章
- mysql分页查询-limit
分页查询的sql: select * from table limit 4,10; 4表示查询的索引,索引是从0开始,4表示从第五条数据开始查询,10表示要查询多少条数据,10表示查询十条数据 如果从 ...
- Spark踩坑记——数据库(Hbase+Mysql)
[TOC] 前言 在使用Spark Streaming的过程中对于计算产生结果的进行持久化时,我们往往需要操作数据库,去统计或者改变一些值.最近一个实时消费者处理任务,在使用spark streami ...
- [转]Spark 踩坑记:数据库(Hbase+Mysql)
https://cloud.tencent.com/developer/article/1004820 Spark 踩坑记:数据库(Hbase+Mysql) 前言 在使用Spark Streaming ...
- Spark踩坑记——数据库(Hbase+Mysql)转
转自:http://www.cnblogs.com/xlturing/p/spark.html 前言 在使用Spark Streaming的过程中对于计算产生结果的进行持久化时,我们往往需要操作数据库 ...
- Spark踩坑记——共享变量
[TOC] 前言 Spark踩坑记--初试 Spark踩坑记--数据库(Hbase+Mysql) Spark踩坑记--Spark Streaming+kafka应用及调优 在前面总结的几篇spark踩 ...
- Spark踩坑记——Spark Streaming+Kafka
[TOC] 前言 在WeTest舆情项目中,需要对每天千万级的游戏评论信息进行词频统计,在生产者一端,我们将数据按照每天的拉取时间存入了Kafka当中,而在消费者一端,我们利用了spark strea ...
- Spark踩坑记——从RDD看集群调度
[TOC] 前言 在Spark的使用中,性能的调优配置过程中,查阅了很多资料,之前自己总结过两篇小博文Spark踩坑记--初试和Spark踩坑记--数据库(Hbase+Mysql),第一篇概况的归纳了 ...
- 记一次 Spring 事务配置踩坑记
记一次 Spring 事务配置踩坑记 问题描述:(SpringBoot + MyBatisPlus) 业务逻辑伪代码如下.理论上,插入数据 t1 后,xxService.getXxx() 方法的查询条 ...
- Spark踩坑记:Spark Streaming+kafka应用及调优
前言 在WeTest舆情项目中,需要对每天千万级的游戏评论信息进行词频统计,在生产者一端,我们将数据按照每天的拉取时间存入了Kafka当中,而在消费者一端,我们利用了spark streaming从k ...
随机推荐
- 【maven】pom.xml中"spring-boot-maven-plugin"报红问题
问题原因 插件下载速度太慢了,即是从国外的中央仓库里下载的. 没有刷新maven spring-boot-maven-plugin没加版本号(有些电脑不加版本号,也是不会爆红的) 问题解决 maven ...
- 分享一个PHP登录小妙招
待完善 思想参照fastadmin api 文件路径 /fastadmin/application/common/library/Auth.php->login().logout().isLog ...
- layui中的分页laypage
1.html部分 <div id="test1"></div> 2.js部分: <script src="/static/build/lay ...
- 小技巧!CSS 提取图片主题色功能探索
本文将介绍一种利用 CSS 获取图片主题色的小技巧.一起看看~ 背景 起因是微信技术群里有个同学发问,有什么方法能够获取图片的主色呢?有一张图片,获取他的主色调: 利用获取到的这个颜色值,来实现类似这 ...
- 【java框架】SpringBoot(7) -- SpringBoot整合MyBatis
1.整合MyBatis操作 前面一篇提到了SpringBoot整合基础的数据源JDBC.Druid操作,实际项目中更常用的还是MyBatis框架,而SpringBoot整合MyBatis进行CRUD也 ...
- 05.24 ICPC 2019-2020 North-Western Russia Regional Contest复现赛+Codeforces Round #645 (Div. 2)
A.Accurate Movement(复现赛) 题意:两个木块最左边都在0的位置,最右边分别为a,b(b>a),并且短的木条只能在长木条内移动,问两个木条需要移动多少次才能使两个木条的右端都在 ...
- 前端必读:Vue响应式系统大PK
转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者. 原文参考:https://www.sitepoint.com/vue-3-reactivity-system ...
- uni-app 微信支付
小程序 支付 先看官方文档 https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_8_2.shtml 知晓有那些比不可少的流程,之后后端 ...
- 【vue2】(一)基础使用
[vue2](一)基础使用 MVVM MVVM: View - Model - ViewModel View: Dom层,视图层 Model: Plain JavaScript Objects,数据层 ...
- 7.CentOS文件和目录 以及系统与设置命令
CentOS文件和目录 etc------系统中的配置文件 bin------系统预设执行文件的放置目录 sbin------系统预设执行文件的放置目录 usr------系统预设执行文件的放置目录 ...