一次 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 会隐藏多久😂

相关推荐
xianwu54311 分钟前
反向代理模块kfj
开发语言·网络·数据库·c++·mysql
SomeB1oody16 分钟前
【Rust中级教程】2.8. API设计原则之灵活性(flexible) Pt.4:显式析构函数的问题及3种解决方案
开发语言·后端·性能优化·rust
李恩1138 分钟前
Mysql 主从集群同步延迟问题怎么解决
mysql
m0_748255412 小时前
深入了解 MySQL:从基础到高级特性
数据库·mysql·adb
Asthenia04122 小时前
基于 MyBatis PageHelper 自定义 PageUtil 的分页实践指南
后端
Hamm3 小时前
封装一个优雅的自定义的字典验证器,让API字典参数验证更湿滑
java·spring boot·后端
刘立军3 小时前
本地大模型编程实战(22)用langchain实现基于SQL数据构建问答系统(1)
人工智能·后端·llm
林林总肿3 小时前
后端mySQL很容易犯的bug,bug记录解决
数据库·mysql·bug
刘立军3 小时前
本地大模型编程实战(21)支持多参数检索的RAG(Retrieval Augmented Generation,检索增强生成)(5)
人工智能·后端·llm
m0_748250744 小时前
Spring Boot 多数据源解决方案:dynamic-datasource-spring-boot-starter 的奥秘(上)
java·spring boot·后端