Mybatis MySQL数据库分页查询出现重复数据

MySQL分页查询出现重复数据

情景(situation):
  今天在生产环境,业务同事导出文件时遇到了出现重复数据的问题。因为之前这个功能是我和我带的外包同事一起做的,所以很熟悉这块代码。经过线上操作核对,和代码检测,发现线上查询确实出现了重复数据,而导出文件出现重复数据是因为导出功能后面使用的接口是我提供的分页接口。通过代码分析,基本确认后台应用端代码应该是没有问题的,那么问题就出现在我提供接口的微服务模块。

任务(task):
  接下来的任务就是找出问题所在。然后就开始分析我微服务模块的代码,经过仔细检查,发现代码逻辑层面是没有问题的,因为前几页的分页都是成功的,但是问题出现在后续几页的数据中,而且在这几页之后的数据又是正常的。那也就是中间那些数据出现了重复。
  通过运维同事查看数据库,发现数据库中对应的数据并没有出现重复,排除了数据插入重复的可能,也就是数据写入判重的代码没有问题。
  此时,通过观察重复数据,发现一个特征,也就是重复数据的配置时间(config_tm)字段值都相同,而这个字段是当时需要说明上要求,数据按照修改时间倒叙排列,所以当时取了这个字段做排序。通过网上搜索MySQL分页数据重复,找到了相关问题,也有人遇到了这个问题。到这里我们大概找到了问题的解决方案,但是秉持严谨的工作态度,接下来准备在测试环境重现这个问题。

行动(action):
  经过在测试环境构造有相同配置时间的测试数据,我们顺利的重现了这个问题。解决问题的方式也很简单,就是在原来排序字段的基础上,再增加一个排序字段,这个字段的区分度最好高一些,避免出现之前重复数据的问题。

  下面是拓展项,我在学习MySQL的过程中,我依稀还记得数据在做排序的时候,如果排序字段A是索引排序,则主键索引会默认作为最后一个字段排序,也就是说,如果存在A字段相同的情况,数据应该会按照主键排序,为了验证是否存在这种情况,我在上面问题的基础上做了一下实验:

  当使用A字段排序时(A字段不是索引字段),不论是升序排列还是降序排列,如果不显示指定最后使用id字段排序,分页还是会出现重复数据问题。
  当使用A字段排序时(A字段是索引字段),不论是升序排列还是降序排列,如果不显示指定最后使用id字段排序,分页还是会出现重复数据问题。

也就是说,不论字段A是不是索引字段,不论A是升序降序,如果不显示指定第二排序字段,数据库分页查询还是会出现重复问题。也就是说默认的主键排序并没有生效。

结果(result):
  通过今天的案例,让我们学习到了,数据库使用order by给查询结果排序时是不稳定的,我们指定排序字段时应该尽量选择区分度比较大的字段,如果第一排序字段区分度不够大,则可以考虑增加第二排序字段。
同时,今天也借此机会验证了,MySQL数据库order by排序时,默认使用主键索引作为隐形的最后排序字段在这个分页过程中并没有生效。

你可能感兴趣的:(踩坑日记)