现象描述
在浏览器上多次刷新同一个页面,发现同一区域的数据会时多时少。
查看接口响应发现同一接口多次请求会返回不一样的数据。
正常情况
页面显示
接口响应
异常情况
页面显示
接口响应
正常接口响应与异常接口响应数据量对比
问题定位
猜测一:负载均衡问题
多个不同版本的应用实例,代码实现或者数据库数据不同导致。
经过排查,开发和测试环境都存在一样的问题,并且这两个环境都是单实例的。
猜测二:代码逻辑有误
走查了代码,发现这里只是一个简单的单表查询,并没有复杂逻辑。
同时针对单个接口反复测试,无法重现响应数据时多时少的问题。
目前看,这块的代码并没有很直观的错误。
猜测三:sql 多次执行返回不同结果
使用查询语句,多次重试,没有复现异常。
猜测四:
经过猜测二、三的排查,怀疑是页面上多个请求同时发起共同导致的问题。
于是反复刷新页面,查看后端日志,发现正常情况与异常情况时执行的 sql 不一致。
异常情况下,会在正常的 sql 后面添加 limit
子句。
到这里,我只能猜测是 mybatis 动态生成的 sql 有问题。
那么什么原因导致会在正常的 sql 后添加 limit 子句,并且这个 5
是从哪里来的呢?
原因分析
在度娘上以 “mybatis 自动添加 limit” 为关键字搜索,发现由于 PageHelper 插件自动添加 limit 的问题很多。
在 Mybatis-PageHelper 的使用方法文章中有如下说明:
由此,可能的原因是在这个页面上的其他请求带有分页,同时由于后端对 Mybatis PageHelper 的使用不规范导致。
页面上有分页的请求
在排查了该接口的代码后发现:代码中调用 PageHelper.startPage
方法的地方与真正执行查询的代码中间有很多复杂的业务处理。
问题原因基本清楚了。
解决方案
- 永久的解决方案:规范
PageHelper.startPage
方法的使用,只在真实查询要执行前,调用该方法,确保安全分页。 - 临时的解决方案:在出现问题的查询前面,调用
PageHelper.clearPage
目前按照临时解决方案进行了处理,反复测试以后,问题得到了解决。