一条 update 语句引起的事故,这回可以长长记性了
点击上方“码农突围”,马上关注
这里是码农充电第一站,回复“666”,获取一份专属大礼包
真爱,请设置“星标”或点个“在看
最近经常碰到开发误删除误更新数据,这不,他们又给我找了个麻烦,我们来看下整个过程。
过程
由于开发需要在生产环节中修复数据,需要执行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进行了解析
赶紧和开发确定了操作的时间点,生成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: 1select_type: SIMPLEtable: tbl_nametype: index
possible_keys: NULLkey: idx_strkey_len: 33ref: NULLrows: 4filtered: 100.00Extra: 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的语法高亮发现相应的问题。
来源 | https://fordba.com/mysql-double-quotation-marks-accident.html
- END -
最近热文• 你偷看的小黄片,全被监视了• 一女程序员被判 9 个月:因薪酬等问题离职,rm -f * 删库,瘫痪 6 个小时• 2021年8月全国程序员薪酬终于出炉了!北京以18904元位居榜首• 外包干三年,必废!• 程序员在深圳买千万豪宅,被领导知道后,被打2星!
一条 update 语句引起的事故,这回可以长长记性了相关推荐
- 一条 update 语句引起的事故,这回让开发长长记性!!
作者 | Harvey 来源 | https://www.fordba.com/mysql-double-quotation-marks-accident.html 一.前言 最近经常碰到开发误删除误 ...
- mysql update from 语句_MySQL高频面试题01期:一条update语句的生命历程
在有关 MySQL 的面试时,是不是曾经有被问到过:一条 update 语句的生命历程是怎样的?今天就来聊聊这一面试题. 这篇文章通过这条语句进行讲解: update test set a=5 whe ...
- mysql 合并两个update_如何将多条update语句合并为一条
需求: 如何将多条update语句合并为一条update语句: 如,update table1 set col='2012' where id='2014001' update table1 set ...
- mysql执行两条update语句
执行两条update语句,没有join关联时 update dp_auto_group_price dagp ,dp_auto_group dag set dagp.is_pub = 0 ,dag.s ...
- InnoDB:一条update语句执行过程
存储引擎InnoDB下执行一条update的语句要经过哪些步骤呢?假设我们执行如下SQL,本文宏观上将执行器和存储引擎视为一体(执行器和存储引擎交互). update user_info set na ...
- 很多条update语句mysql优化_MySQL批量update语句优化
对MySQL中的表进行批量update的时候,如果每个记录用一个update语句,5000条记录的话,大概需要30秒钟.下面采用的case when方法可以把5000条update拼成一条: Upda ...
- 一条 update 语句的生命历程
在有关 MySQL 的面试时,是不是曾经有被问到过:一条 update 语句的生命历程是怎样的?今天就来聊聊这一面试题. 这篇文章通过这条语句进行讲解: update test set a=5 whe ...
- 动手为王:由一条UPDATE语句引发的一波三折深入实践(含PPT)
关注我们获得更多精彩 编辑说明:这篇文章源自我几年前的一个演讲,当时我在『甲骨文技术大会』分享了一个关于SQL的主题,其中的一个案例推演了几个步骤,后来本文作者『刘晨』做了验证.实验,并且分享在他的博 ...
- 一条update语句在MySQL内部是如何执行的
一.Server层阶段 1.连接器:负责跟客户端建立连接.获取权限.维持和管理连接 2.分析器:验证通过以后,分析器会对该语句分析, 判断是否语法有错误等. 3.优化器:选择索引,生成执行计划. 4. ...
- mysql基础架构(一条update语句如何执行)
update语句如何执行? 一.流程分析 二.重要的日志模块 1.redo log 2.binlog 3.两阶段提交 三.小结 一.流程分析 与查询流程不一样的是,更新流程涉及,两个重要的日志模块,r ...
最新文章
- 2.11 计算机视觉现状-深度学习第四课《卷积神经网络》-Stanford吴恩达教授
- 释疑の语法LOCAL
- 制作bpmn html,BPMN 2.0规范详解
- 困难时拉你一把的图片_2019早上好表情图片合集 早晨祝福语动画
- NewCode----给定两个数R和n,输出R的n次方
- 发送邮件现在应用得最多的两种情况就是利用.NET自带的发送邮件和利用jmail组件来发送邮件。...
- 在ubuntu 16.04中安装source insight 4.0破解版
- 【云计算平台】VMware搭建Centos 7虚拟机
- amd锐龙笔记本cpu怎么样_AMD的锐龙处理器怎么样?AMD的市占率高吗?
- ubuntu16.04--cuda
- LeetCode 144. 二叉树的前序遍历(递归)(迭代)(颜色标记法)
- SVN回退到之前的版本
- 防火墙和代理服务器之间有什么区别
- C#中的事件(event)
- 论文笔记:残差神经网络(ResNet v1)
- 下级对上级回复已阅知_下级对上级回复已阅知_工作中回复领导,绝不能用OK!除此之外,还有四条...
- 领英大数据:经济寒冬,“全思维IT工程师”成企业新宠
- Git submodule 采坑
- 实力踩坑:There is no getter for property named ‘XXX‘ ‘class XXX‘
- C++ new malloc