当前位置: 首页 > news >正文

把sql拿到数据库中执行,和程序返回的值不一样??????

前言

大家好,我是大飞!
一个mybatis缓存引发的问题,消耗一桶泡面,耗时3小时才解决。本篇文章主要是分享解决问题、分析问题的过程,如果大家平时很少通过debug源码的方式去解决问题,不妨大家看看我下面的分析问题思路,以及debug源码的流程。我相信还是可以帮到大家的。

问题描述

今天下午快下班了,产品说线上有bug,然后同事小王去排查去了,说好奇怪呀,为啥直接去数据库查的时候没有数据,但是程序打断点确有数据。然后同事们纷纷围了上去,大家都发现好奇怪呀,看见小王束手无策的样子,我的另一个同事王麻子就说让我来看看。王麻子看了一会,摇摇头说,奇怪执行了这个mapper接口居然没打sql,其他的mapper 都打了sql日志的呀。

问题eg:List ret = mapper.select(Obejct parameter); sql 在数据库中执行没有值的。但是程序输出的结果ret确为1。

大家都没找到原因,于是我大飞也加入了战斗,下面我们就开始分析,排查吧!


排查思路:

小王说程序给的结果和把sql直接去数据库查的不一样,王麻子说,这个mapper接口没有打印日志

1. 会不会不是执行的这个mapper,难道是有两个同样的mapper接口。

为什么我会这么想呢,因为我们这个工程里面包含两个项目的包,启动其中一个项目,两个项目的代码都会加载进去。我就在想会不会是注入混了。全局搜索了一下没有发现同名的mapper也没有同名的service。

2.只有打断点进入mybatis源码,看看sql是否和mapper写的一样

进入mapper代理执行的内部,一步一步往下走,中间无数步就忽略,最终到了excutor.query了(org.apache.ibatis.session.defaults.DefaultSqlSession selectList方法),看ms里面的sqlSource,以及parameter都和预期的一样。于是到了这儿我还是没发现问题
在这里插入图片描述

3.进入深入debug,发现关键问题。

进入到上一步,还是没有发现sql有啥问题,我就继续深入的debug,直到我debug到org.apache.ibatis.executor query方法152方法时,发现localCache,我就明离真相不远了。
在这里插入图片描述

可以看到这个地方已经出现了localCache,确实数据的值是从localCache取出来的,但是从cache里面取出来的值就有问题了,而且Cache 缓存的key信息里面包含了sql和入参,sql和入参和预期的值是一样的,就是value不是预期值。这时候我就想既然缓存里面有只,那么在某一步肯定是提前put了的,所以我就在put的方法打了断点。
在这里插入图片描述

因为这个执行sql的地方肯定很多,所以我这个地方的短单就打了一个条断点key.toString().equals("-1616...."),重新调试进入了我预期的put 方法,我以此时的value是有值的,但是并非我所愿,这个地方的value是没有值的,也就是和sql执行的结果一样,无数据。

到了这一步,我可以肯定的是sql和参数确实是没有被修改,因该是缓存结果被修改了,或者说是中途有put了一次把数据放进去了。无赖只有继续往下周,看看是不是中途,有什么拦截器,把值给我修改了

继续往下走,又到了执行我那个有问题的sql了,发现到了我这儿缓存里面的值就变成了List.size == 1的情况了。

看到这儿不知道他家有啥想法没?
也就是说我这个sql 在我这个业务逻辑中,确实有两个地方执行了,第一次执行返回的list.size == 0,等于0也是我们期望的值,并且第一次执行了就放到缓存了。第二次执行同样的sql,就直接从缓存中取,按理说取出来的也是kong,但是取出来确有值了。。。。

4.找到问题代码

到这儿大概原因我是明白了,放进缓存中的值是没有问题,并且后续也没有再重新put值进了(通过debug put方法得出),剩下的可能就是这个value值被修改了。回到第一个执行mapper接口的地方,我终于发现问题了。
伪代码:

List ret = mapper.select(Obejct parameter); 
ret.add(1234l)

TMD,第一次查询sql的时候,在结果集上面加了一个值。。。。导致后面查询来就是这个值。关键是某些场景下面,第二次查询出来的值本身也等于这个add的值,导致测试反应预生产环境没有这个问题。


总结:

看到这儿,原来是开发直接在原有结果集的引用上修改了值,导致后面查询出来的是被修改过的值。第二次查询缓存中的数据,也没有打印sql,让同事们连连叫怪。。。。。最后大家还是不要直接修改mapper结果集的数据。。。。。。。。。

相关文章:

  • 深度学习工具jupyter的new没有环境选项以及遇到的EnvironmentLocationNotFound:Not such a environment
  • Nginx实现动静分离
  • 赋能AI未来,景联文科技推出高质量亿级教育题库、多轮对话以及心理大模型数据
  • 信息检索(53):Document Expansion by Query Prediction
  • Spring框架学习笔记(本地印象笔记搬运)(整理中)
  • TensorRT-LLM加速框架的基本使用
  • 数据库原理与安全复习笔记(未完待续)
  • 【Linux】使用 iptables 验证访问HDFS 所使用到的端口
  • 光纤通讯资料收集
  • java课程设计GUI学生信息管理系统
  • 爬虫阶段思考
  • 【Rust】——所有可能会用到模式的位置
  • Spring Cloud学习:如何实现Gateway 服务网关限流
  • ESP32 esp-idf esp-adf环境安装及.a库创建与编译
  • OpenCV颜色检测
  • 【407天】跃迁之路——程序员高效学习方法论探索系列(实验阶段164-2018.03.19)...
  • 【个人向】《HTTP图解》阅后小结
  • 【腾讯Bugly干货分享】从0到1打造直播 App
  • 11111111
  • create-react-app项目添加less配置
  • ECMAScript入门(七)--Module语法
  • Java 23种设计模式 之单例模式 7种实现方式
  • JAVA 学习IO流
  • js
  • js学习笔记
  • Laravel 中的一个后期静态绑定
  • Linux各目录及每个目录的详细介绍
  • Shadow DOM 内部构造及如何构建独立组件
  • spark本地环境的搭建到运行第一个spark程序
  • SQLServer之索引简介
  • Three.js 再探 - 写一个跳一跳极简版游戏
  • 浮动相关
  • 回流、重绘及其优化
  • 坑!为什么View.startAnimation不起作用?
  • 浅谈Golang中select的用法
  • 使用 Node.js 的 nodemailer 模块发送邮件(支持 QQ、163 等、支持附件)
  • 项目管理碎碎念系列之一:干系人管理
  • 在Mac OS X上安装 Ruby运行环境
  • ​ 轻量应用服务器:亚马逊云科技打造全球领先的云计算解决方案
  • ​3ds Max插件CG MAGIC图形板块为您提升线条效率!
  • ​iOS安全加固方法及实现
  • ​创新驱动,边缘计算领袖:亚马逊云科技海外服务器服务再进化
  • (1)(1.13) SiK无线电高级配置(五)
  • (11)MSP430F5529 定时器B
  • (14)学习笔记:动手深度学习(Pytorch神经网络基础)
  • (6)添加vue-cookie
  • (rabbitmq的高级特性)消息可靠性
  • (备忘)Java Map 遍历
  • (二)换源+apt-get基础配置+搜狗拼音
  • (考研湖科大教书匠计算机网络)第一章概述-第五节1:计算机网络体系结构之分层思想和举例
  • (强烈推荐)移动端音视频从零到上手(下)
  • (一)u-boot-nand.bin的下载
  • (一)WLAN定义和基本架构转
  • ***php进行支付宝开发中return_url和notify_url的区别分析
  • **python多态