问题
这段时间收到了个很奇怪的bug,就是一个数据的分页的时候会有重复的数据。
第一页
第二页
问题挖掘
1.出现了这个问题后我首先对数据库的表结构和数据进行了排查,发现并没有什么问题。
表结构
hs_department` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`customer_id` bigint(20) DEFAULT NULL COMMENT '所属客户',
`status` int(4) DEFAULT '1' COMMENT '状态',
`dname` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '科室名称',
`descrip` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '科室描述',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`is_del` int(1) DEFAULT '0' COMMENT '是否删除(0:未删除 1:已删除)',
`his_id` varchar(11) DEFAULT NULL,
`pinyin` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '科室首拼',
2.发现数据没有问题后去代码里查看底层的SQL语句,运行出来也是没有问题的。
SELECT
his_id,
id,
dname,
customer_id,
create_time,
`status`,
descrip,
pinyin
FROM
hs_department
WHERE
is_del = 0
3.然后我想到分页的底层是使用limit,去尝试了下果然出问题了,limit分页出来两次会有重复。
问题排查
在MySQL 5.6的版本上,优化器在遇到order by limit语句时,做了个查询优化,即使用了priority queue(优先级队列)。采用priority queue能够根据limit N维护一个大小为N的堆,在排序的过程中,只用保留N条记录即可。但堆排序是一个不稳定的排序算法,所以当排序字段值存在重复时,返回的数据顺序可能会不一样,其中一个影响因素就是limit。
解决方案
查询语句加上order by id(保证排序字段的唯一性),上线后,问题得到解决。