首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >同事写了个SQL,双引号错位,生产数据全变0了!

同事写了个SQL,双引号错位,生产数据全变0了!

作者头像
Guide哥
发布于 2021-02-09 13:25:01
发布于 2021-02-09 13:25:01
59200
代码可运行
举报
文章被收录于专栏:JavaGuideJavaGuide
运行总次数:0
代码可运行

原文:https://sourl.cn/pqLJz4

MySQL 中一个双引号的错位引发的血案!值得一看,避免自己踩坑!

一、前言

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

二、过程

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

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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[1]

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

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

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
update tbl_name set str_col="xxx" = "yyy"

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
update tbl_name set (str_col="xxx" )= "yyy"

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
update tbl_name set str_col=("xxx" = "yyy")

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
select "xxx" = "yyy"

的值是 0,所以

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
update tbl_name set str_col="xxx" = "yyy"

等价于

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
update tbl_name set str_col=0

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

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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'的记录也查找出来了,为什么呢?

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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 条件转化成了

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
((`test`.`tbl_name`.`str_col` = 'xxx') = 'yyy')

这个条件的首先判断 str_col 和'xxx'是否相等,如果相等,那么里面括号的值为 1,如果不相等,就是 0 然后 0 或者 1 再和和'yyy'进行判断, 由于等号一边是 int,另外一边是字符串,两边都转化为 float 进行比较,可以看我之前的一篇文章MySQL 中隐式转换导致的查询结果错误案例分析[2]'yyy'转化为浮点型为 0,0 和 0 比较恒等于 1

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 select id,str_col from tbl_name where 1=1;

将查询出所有的记录。

三、小结

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

参考资料

[1]

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

[2]

MySQL中隐式转换导致的查询结果错误案例分析: https://www.fordba.com/mysql-type-convert-analysis.html

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-01-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 JavaGuide 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
MySQL 中一个双引号的错位引发的血案
最近经常碰到开发误删除误更新数据,这不,他们又给我找了个麻烦,我们来看下整个过程。
芋道源码
2018/12/24
8620
MySQL中一个双引号的错位引发的血案
由于开发需要在生产环节中修复数据,需要执行120条SQL语句,需要将数据进行更新于是开发连上了生产数据库,首先执行了第一条SQL
用户1278550
2019/07/24
7300
MySQL中一个双引号的错位引发的血案
MySQL由一个双引号引发的血案
最近经常碰到开发误删除误更新数据,这不,他们又给我找了个麻烦,我们来看下整个过程。
Bug开发工程师
2018/12/29
7740
把我坑惨的一个MySQL双引号!
www.fordba.com/mysql-double-quotation-marks-accident.html
Java技术栈
2019/07/04
3.1K0
一条 update 语句引起的事故,这回可以长长记性了
最近经常碰到开发误删除误更新数据,这不,他们又给我找了个麻烦,我们来看下整个过程。
用户2781897
2021/06/09
6630
一条 update 语句引起的事故,这回可以长长记性了
这次被坑惨了,MySQL的隐式转换导致了一个线上BUG
某一天,开发问我,为什么针对一个查询会有两条记录,且其中一条记录并不符合条件select * from tablea where xxno = 170325171202362928;xxno为 170325171202362928 和 170325171202362930的都出现在结果中。
用户1516716
2020/07/28
5540
[715]python binlog2sql同步mysql数据
binlog是记录所有数据库表结构变更(例如CREATE、ALTER TABLE…)以及表数据修改(INSERT、UPDATE、DELETE…)的二进制日志。
周小董
2020/01/13
2.1K0
[715]python binlog2sql同步mysql数据
使用binlog2sql针对mysql进行数据恢复
DBA或开发人员,有时会误删或者误更新数据,如果是线上环境并且影响较大,就需要能快速回滚。传统恢复方法是利用备份重搭实例,再应用去除错误sql后的binlog来恢复数据。此法费时费力,甚至需要停机维护,并不适合快速回滚。也有团队利用LVM快照来缩短恢复时间,但快照的缺点是会影响mysql的性能。
大道七哥
2019/09/10
9580
binlog2sql,你该知道的数据恢复工具
今天分享一下binlog2sql,它是一款比较常用的数据恢复工具,可以通过它从MySQL binlog解析出你要的SQL,并根据不同选项,可以得到原始SQL、回滚SQL、去除主键的INSERT SQL等。主要用途如下:
俊才
2020/09/24
2.2K0
MySQL基于Binlog的数据恢复实战
操作系统:CentOS 7.7 MySQL版本:5.7.30,搭建主从 开启binlog,binlog_format=row 备份情况:每天00:00对数据库进行全量备份 恢复原因:某日22:00左右,执行了批量update语句,需要回滚
仙人技术
2021/09/29
2.5K0
MySQL基于Binlog的数据恢复实战
MySQL常用命令总结
https://cloud.tencent.com/developer/article/1925495
DBA札记
2024/02/23
1640
MySQL常用命令总结
MySQL DML 数据操作
如果发现表中已经有此行数据(根据主键或者唯一索引判断)则先删除此行数据,然后插入新的数据,否则直接插入新数据。
恋喵大鲤鱼
2023/10/12
3860
MySQL特有的SQL语句 第一弹
关于SQL,我们总是会有无穷无尽相关的话题,有时候碰到了一些觉得不错的SQL功能会标记下来,好记性不烂烂笔头,回头来看,自己也收集了不少的点子,但是从整体来看,可能仅仅是一瓢水而已。大家有好的想法也欢
jeanron100
2018/03/21
1.2K0
MySQL特有的SQL语句 第一弹
mysql 数据库备份和恢复
物理备份是指直接复制包含数据的文件夹和文件。这种类型的备份适用于大数据量且非常重要,遇到问题需要快速回复的数据库。
WindWant
2020/09/11
4.3K0
分库分表之第五篇
电商平台商品列表展示,每个列表项中除了包含商品基本信息、商品描述信息之外,还包括了商品所属的店铺信息,如下 :
海仔
2020/02/11
6640
10分钟学会理解和解决MySQL乱码问题
本文将详细介绍MySQL乱码的成因和具体的解决方案。在阅读本文之前,强烈建议对字符集编码概念还比较模糊的同学 阅读下博主之前对相关概念的一篇科普:十分钟搞清字符集和字符编码 MySQL出现乱码的原因
小小科
2018/05/03
1.3K0
10分钟学会理解和解决MySQL乱码问题
Mysql基础篇--面试sql优化
3.匹配最左前缀匹配,仅仅对索引中最左列进行查询,比如复合索引 col1+col2+col3 ,使用索引的是 col1+col2,col1+col3,col1+col2+col3,不会使用索引的是col2+col3,col2.
小土豆Yuki
2020/06/15
8540
SQL优化篇:如何成为一位写优质SQL语句的绝顶高手!
写SQL语句不难,稍微系统学习过数据库相关技术的人都能做到,但想要写好SQL却也不是一件易事,在大多数编写SQL的时候,很多人都是以实现需求为原则去撰写的,当一条SQL写出来之后,只要能满足业务需求就行,不会考虑它有没有优化点,能不能让它跑的更快。
田维常
2023/08/31
1.9K0
SQL优化篇:如何成为一位写优质SQL语句的绝顶高手!
MySQL 之 视图、触发器、存储过程、函数、事物与数据库锁
浏览目录: 1.视图 2.触发器 3.存储过程 4.函数 5.事物 6.数据库锁 7.数据库备份 1.视图 视图:是一个虚拟表,其内容由查询定义。同真实的表一样,视图包含一系列带有名称的列和行数据 视图有如下特点;   1. 视图的列可以来自不同的表,是表的抽象和逻辑意义上建立的新关系。   2. 视图是由基本表(实表)产生的表(虚表)。   3. 视图的建立和删除不影响基本表。   4. 对视图内容的更新(添加、删除和修改)直接影响基本表。
人生不如戏
2018/04/10
1.7K0
MySQL 之 视图、触发器、存储过程、函数、事物与数据库锁
干货!超过500行的Mysql学习笔记
本文介绍了软件测试的基本流程和常用的测试工具。软件测试的基本流程包括需求分析、设计、编程、测试、部署和维护。常用的测试工具有QTP、Selenium、JMeter、LoadRunner等。
企鹅号小编
2018/01/09
1.4K0
干货!超过500行的Mysql学习笔记
相关推荐
MySQL 中一个双引号的错位引发的血案
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档