一个update,误用一个双引号,生产数据全变0了

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介: 一个update,误用一个双引号,生产数据全变0了

一、前言

 

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

 

二、过程

 

由于开发需要在生产环节中修复数据,需要执行120条SQL语句,需要将数据进行更新,于是开发连上了生产数据库,首先执行了第一条SQL

 

 

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

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

 

 

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

 

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

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

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

binlog2sql https://github.com/danfengcao/binlog2sql

 

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

 

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

 

这几条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 0=0;

+-----+

| 0=0 |

+-----+

|   1 |

+-----+

1 row in set (0.00 sec)

 

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

 

 

select id,str_col from tbl_name where 1=1;

 

将查询出所有的记录。

 

三、小结

 

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

 

 

PS:如果觉得我的分享不错,欢迎大家随手点赞、在看。

相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
feof用法重点详解(易被误用判断文件结束!!!)
feof用法重点详解(易被误用判断文件结束!!!)
|
11月前
|
SQL 关系型数据库 MySQL
mysql varchar类型字段为数字时,不带引号查询时查询结果与事实不符
mysql varchar类型字段为数字时,不带引号查询时查询结果与事实不符
327 1
|
SQL IDE 关系型数据库
同事写了一个update,误用一个双引号,生产数据全变0了!
一、前言 最近经常碰到开发误删除误更新数据,这不,他们又给我找了个麻烦,我们来看下整个过程。
同事写了一个update,误用一个双引号,生产数据全变0了!
|
Java
Java基础—消除敏感字并替换逻辑
在日常使用聊天软件或游戏交流时,当出现不文明词语会被”和谐“,那么这个逻辑是怎么实现的呢?本文展示如何用Java实现敏感字过滤并替换的逻辑代码。
2750 2
|
SQL
SQL基础【十八、事物】(sql事物慎用,还是写业务逻辑代码好一些,入伙涉及到更换数据啥的很麻烦!)(二)
SQL基础【十八、事物】(sql事物慎用,还是写业务逻辑代码好一些,入伙涉及到更换数据啥的很麻烦!)(二)
127 0
SQL基础【十八、事物】(sql事物慎用,还是写业务逻辑代码好一些,入伙涉及到更换数据啥的很麻烦!)(二)
|
SQL 安全 数据处理
SQL基础【十八、事物】(sql事物慎用,还是写业务逻辑代码好一些,入伙涉及到更换数据啥的很麻烦!)(一)
SQL基础【十八、事物】(sql事物慎用,还是写业务逻辑代码好一些,入伙涉及到更换数据啥的很麻烦!)(一)
107 0
SQL基础【十八、事物】(sql事物慎用,还是写业务逻辑代码好一些,入伙涉及到更换数据啥的很麻烦!)(一)
|
SQL 数据库
SQL基础【十八、事物】(sql事物慎用,还是写业务逻辑代码好一些,入伙涉及到更换数据啥的很麻烦!)(三)
SQL基础【十八、事物】(sql事物慎用,还是写业务逻辑代码好一些,入伙涉及到更换数据啥的很麻烦!)(三)
116 0
SQL基础【十八、事物】(sql事物慎用,还是写业务逻辑代码好一些,入伙涉及到更换数据啥的很麻烦!)(三)
sprintf参数包含本身时,结果并不符合预期
sprintf参数包含本身时,结果并不符合预期
122 0
|
设计模式 Java 程序员
细微之处见真章之字符串超长省略功能
细微之处见真章之字符串超长省略功能
185 0
重构——33以字段取代子类(Replace Subclass with Fields)
以字段取代子类(Replace Subclass with Fields):你的各个子类的唯一差别只在“返回常量数据”的函数上:修改这些函数,使他们返回超类的某个新增字段,然后销毁子类
1232 0