一次 MySQL IF 函数的误用导致的生产小事故

事件起因

这起生产小事故其实还是七月份的事情,本来早就准备写篇博客记录下,但由于各种原因拖到了现在才写,附上当时的提交记录:

简要的来说就是有两张表,一张资源表,一张资源收藏表,每个用户收藏了某个资源就会在资源收藏中进行记录,如果取消收藏,则从收藏表进行删除。在开发阶段该功能一切正常,但是生产环境会出现收藏后在表中添加了记录,但是界面是始终展示的未收藏的效果,同时多次点收藏都会在表中添加记录,但是界面上始终显示的是未收藏。由于该功能是直接从以往项目代码中复制而来,当现场实施人员反馈这个问题时,几个同事也都在本地进行了测试并且功能一切正常,但都没有发现代码有什么问题,问题一时陷入僵局。。。

发现问题

在排查的过程中我发现该功能的查询直接是使用原生 SQL 进行查询,并且页面中展示是否收藏是通过if(resource_id,'1','0') isFavorite(resource_id 是资源收藏表中的字段)来查询资源是否已在收藏表中存在。然后我就先调试代码再将执行的SQL复制直接执行,但都没发现问题,返回结果也一切正常。这时我就想会不会是现场数据或者配置有什么问题,因此我就将执行的 SQL 直接进行了执行,结果收藏表中有数据,isFavorite字段却还是 0,思索了一会,我就在查询字段中直接添加了resource_id字段,这是发现查询结果中resource_id字段有值,isFavorite却为 0。然后我就把查询得到的resource_id直接带入了if(resource_id,'1','0'),结果竟然真的是0,我一时有些懵逼。又过了一会,我决定还是先看一下开发库,并在开发库中重复了上述的步骤,然后不知过了多久(由于已经过去将近半年,我也不记得具体是如何发现以及用了多久),我突然发现开发库的 id 字段都是4开头的UUID字符串格式,生产环境则是f开头的UUID字符串。并且在执行SQL的时候,控制台还出现了类似Truncated incorrect DOUBLE value: 'f12a836542956397'的警告,然后经过查询发现MySQL在计算表达式的时候的确会将字符串转为浮点类型,并且只会从前到后截取字符串中的数字进行转换,这也是上述警告出现的原因。这时我也终于知道了问题的所在,直接将上述的SQL语句改为if(resource_id is not null,'1','0')即可,当然这里改为使用ifnull函数或者直接查询resource_id的值,然后通过代码判断再设置字段也是可以的。

问题总结

总的来说,这个小问题还是对基础掌握不够牢,代码编写不规范导致的。不过,就我个人来说,除非不得已,我不太喜欢在 SQL 中写太多逻辑(记不住那么多SQL语法哈哈,当然随着GPT的出现,让AI去写还是很方便的),还是喜欢在代码中处理。以上就是对这次小事故的一个总结,文中结论如有错误之处,也欢迎在评论区交流讨论。

题外话

如果不是因为这次生产环境生成的UUID 是非非数字开头,还不知道这个 bug 会隐藏多久😂

相关推荐
Cobyte20 分钟前
AI全栈实战:使用 Python+LangChain+Vue3 构建一个 LLM 聊天应用
前端·后端·aigc
程序员侠客行1 小时前
Mybatis连接池实现及池化模式
java·后端·架构·mybatis
Honmaple1 小时前
QMD (Quarto Markdown) 搭建与使用指南
后端
PP东2 小时前
Flowable学习(二)——Flowable概念学习
java·后端·学习·flowable
invicinble2 小时前
springboot的核心实现机制原理
java·spring boot·后端
Goat恶霸詹姆斯2 小时前
mysql常用语句
数据库·mysql·oracle
全栈老石2 小时前
Python 异步生存手册:给被 JS async/await 宠坏的全栈工程师
后端·python
space62123272 小时前
在SpringBoot项目中集成MongoDB
spring boot·后端·mongodb
Tony Bai3 小时前
再见,丑陋的 container/heap!Go 泛型堆 heap/v2 提案解析
开发语言·后端·golang
寻找奶酪的mouse3 小时前
30岁技术人对职业和生活的思考
前端·后端·年终总结