服务器又报警了,这次是MySQL的“断章取义”

我给大家说一下,我日常的工作就是,写 bug,改 bug,背锅。这不昨天又背了一个锅。服务器突然就报警了,我一看有一条请求总是被超时。于是,这问题我得拿下。要不然那天爆发出一个大问题,这就不是背锅这么简单了,那是背铺盖卷儿走人了!虽然话有些严重,但是所有的事故都是由一个微小的举动引起的,我们不得不早早预防!
我通过日志发现超时的这个接口很普通。实际上也就只有一个普通的查询语句,而且 SQL 还特简单。这句 SQL 我脱敏后,整理如下:
其中,id 是一个 key,是一个 bigint 类型的 key。我拿着这种查询语句,执行上百遍都没有任何问题,但是在生产上就是会超时。
百思不得其解,有同事给我说,这条 SQL 他写错了,不应该带单引号的。我然后让他改,下次注意。但是,实际上加了单引号了也没问题,也可以查询。并且通过 explain 显示,并没有什么问题。
我知道有人会说,MySQL 在类型不匹配的时候,会放弃索引的。是的,大多数情况下你这样说是对的。但是,在我们今天这种情况下,你这样说就不对了。因为,上面的查询,是走索引的。那么问题出在哪里呢?原因是在 MySQL 中当字符串和数字比较时会把字符串转化为数字。如果是无法转换成数字的字符串都被转换成 0 来处理,也就是说无法转换成数字的字符串都会被转换成 0。
这样以来上面的语句,也就等价于下面的语句。
既然是这样,哪为什么还会出现超时的情况呢?而且是经常出现?
于是,我去查了查 MySQL 的慢查询。发现有这样一条 SQL 语句,脱敏后 SQL 语句如下所示:
我怎么说查询会超时,并且那个开发人员用字符串呢?搞半天传进来了这样的查询参数。其中项目上的漏洞,我先不说,我们今天就来说说这条 SQL 语句,为什么会超时呢?
根据《高性能 MySQL》中的内容显示,这条语句的执行过程是这样的。这个查询参数被 MySQL 截断了,原因是超过了 bigint 类型的长度。假设截断后是 1314520,那么 SQL 就拿这个 1314520 去匹配索引,因为是 select * 所以要回表。然后表中等于 1314520 的数据量非常的大,然后通过 1314520 查询到的数据从引擎层返回到 server 层,比较字符串后发现与 1314520xttblog 不相等,所以全部丢弃返回空。
MySQL 的这个“断章取义”真是害人不浅啊,蒙蔽了大家的双眼。另外我的设计也是有些问题的,这个我们以后再表。
MySQL 这个巨人现在也是非常落后了,AiSQL 和 MariaDb 都比它强。主要原因是 Oracle 才是亲儿子,这个捡的孩子不讨人喜欢!MySQL 的这种状态导致它的分支也一大堆,如果我们每个分支都学一下,学习成本要高出不少。
本站所有文章均由网友分享,仅用于参考学习用,请勿直接转载,如有侵权,请联系网站客服删除相关文章。若由于商用引起版权纠纷,一切责任均由使用者承担
极客文库 » 服务器又报警了,这次是MySQL的“断章取义”

Leave a Reply

欢迎加入「极客文库」,成为原创作者从这里开始!

立即加入 了解更多