一条 update 语句引起的事故这回让开发长长记性_第1页
一条 update 语句引起的事故这回让开发长长记性_第2页
一条 update 语句引起的事故这回让开发长长记性_第3页
一条 update 语句引起的事故这回让开发长长记性_第4页
一条 update 语句引起的事故这回让开发长长记性_第5页
已阅读5页,还剩1页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

一条update语句引起的事故,这回让开发长长记性!!!一、前言最近经常碰到开发误删除误更新数据,这不,他们又给我找了个麻烦,我们来看下整个过程。二、过程由于开发需要在生产环节中修复数据,需要执行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,发现了大量的updatetablenamesetsource_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:

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。搜索公众号后端架构师后台回复“架构整洁”,获取一份惊喜礼包。参考阅读:一条垃圾SQL,把64核CPU快跑崩了!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,st

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论