MySQL中一个双引号错位引发的血案

栏目: 数据库 · 发布时间: 6年前

内容简介:最近经常碰到开发误删除误更新数据,这不,他们又给我找了个麻烦,我们来看下整个过程。由于开发需要在生产环节中修复数据,需要执行120条SQL语句,需要将数据进行更新

MySQL中一个双引号错位引发的血案

一、前言

最近经常碰到开发误删除误更新数据,这不,他们又给我找了个麻烦,我们来看下整个过程。

二、过程

由于开发需要在生产环节中修复数据,需要执行120条 SQL 语句,需要将数据进行更新

于是开发连上了生产数据库,首先执行了第一条SQL

update tablename set source_name = "bj1062-北京市朝阳区常营北辰福第"  
           where source_name =     "-北京市朝阳区常营北辰福第"  

我们仔细看了下,这个SQL,的确没有什么问题,where条件也是正常的,大意就是将这个地址的前面加字符串bj1062,是真的没有错误么?是的没有错误。开发执行完成后,结果的确是符合预期。

然后开发执行了剩下的SQL,都是和上面的SQL一样,将地址进行更新。执行完成后,开发懵逼了,发现source_name都变成了0,开发赶紧给我打电话说:

Harvey,我执行了update,where条件都是对的,set的值也是对的,但是set后的字段全部都变成了0,你赶紧帮我看看,看看能不能恢复数据。

我赶紧登上服务器,查看了这段时间的binlog,发现了大量的update tablename set source_name=0的语句,利用binlog2sql进行了解析,项目地址:binlog2sql

MySQL中一个双引号错位引发的血案

赶紧和开发确定了操作的时间点,生成flashback的SQL,进行了数据恢复,同时保留现场证据。

然后对开发执行的SQL进行了check,发现了几条很诡异的SQL:

MySQL中一个双引号错位引发的血案

这几条SQL的引号位置跑到了where 字段名字后面,简化后的SQL变成了:

update tbl_name set str_col="xxx" = "yyy" 

那么这个SQL在 MySQL 他是如何进行语义转化的呢?

可能是下面这样的么?

update tbl_name set (str_col="xxx" )= "yyy" 

这样就语法错误了,那么只会是下面这样的形式,

update tbl_name set str_col=("xxx" = "yyy") 

select "xxx" = "yyy" 

的值是0,所以

update tbl_name set str_col="xxx" = "yyy" 

等价于

update tbl_name set str_col=0

所以就导致了source_name字段全部更新成了0.

我们再研究下select形式这种语句会怎么样。

mysql [localhost] {msandbox} (test) > select id,str_col from tbl_name where str_col="xxx" = "yyy";  
+----+---------+  
| id | str_col |  
+----+---------+  
|  1 | aaa     |  
|  2 | aaa     |  
|  3 | aaa     |  
|  4 | aaa     |  
+----+---------+  

我们发现,这个SQL将str_col=’aaa’的记录也查找出来了,为什么呢?

mysql [localhost] {msandbox} (test) > warnings  
Show warnings enabled.  
mysql [localhost] {msandbox} (test) > explain extended select id,str_col from tbl_name where str_col="xxx" = "yyy"\G  
*************************** 1. row ***************************  
           id: 1  
  select_type: SIMPLE  
        table: tbl_name  
         type: index  
possible_keys: NULL  
          key: idx_str  
      key_len: 33  
          ref: NULL  
         rows: 4  
     filtered: 100.00  
        Extra: Using where; Using index  
1 row in set, 1 warning (0.00 sec)  
Note (Code 1003): /* select#1 */ select `test`.`tbl_name`.`id` AS `id`,`test`.`tbl_name`.`str_col` AS `str_col` from `test`.`tbl_name` where ((`test`.`tbl_name`.`str_col` = 'xxx') = 'yyy') 

这里他把 where 条件转化成了

((`test`.`tbl_name`.`str_col` = 'xxx') = 'yyy') 

这个条件的首先判断str_col 和’xxx’是否相等,如果相等,那么里面括号的值为1,如果不相等,就是0

然后0或者1再和和’yyy’进行判断,

由于等号一边是int,另外一边是字符串,两边都转化为float进行比较,可以看我之前的一篇文章

MySQL中隐式转换导致的查询结果错误案例分析

‘yyy’转化为浮点型为0,0和0比较恒等于1

mysql [localhost] {msandbox} (test) > select 'yyy'+0.0;  
+-----------+  
| 'yyy'+0.0 |  
+-----------+  
|         0 |  
+-----------+  
1 row in set, 1 warning (0.00 sec)  
mysql [localhost] {msandbox} (test) > select 00=0;  
+-----+ 
| 00=0 |  
+-----+  
|   1 |  
+-----+  
1 row in set (0.00 sec)  

这样导致结果恒成立,也就是 select 语句等价于以下 SQL

select id,str_col from tbl_name where 11=1; 

将查询出所有的记录。

三、小结

在写SQL的过程中,一定要小心引号的位置是否正确,有时候引号位置错误,SQL依然是正常的,但是却会导致执行结果全部错误。在执行前必须在测试环境执行测试,结合IDE的语法高亮发现相应的问题。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Mashups Web 2.0开发技术—— 基于Amazon.com

Mashups Web 2.0开发技术—— 基于Amazon.com

萨拉汉 / 吴宏泉 / 清华大学 / 2008-1 / 48.00元

《MashupsWeb2.0开发技术(基于Amazon.Com) 》介绍了mashup的底层技术,并且第一次展示了如何创建mashup的应用程序。Amazon.com与Web服务强势结合,拓展了Internet的应用范围,使得开发人员可以把Amazon的数据和其他的可利用资源自由地结合起来创建功能丰富的全新应用程序,这种应用程序叫做mashup。 《MashupsWeb2.0开发技术(基于A......一起来看看 《Mashups Web 2.0开发技术—— 基于Amazon.com》 这本书的介绍吧!

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具