一條沒有條件的UPDATE的分析

上周同事有條update SQL沒有加條件就執(zhí)行了敷钾,在DBA大佬的及時(shí)搶救下沒有釀成事故。那條SQL比較有趣乙漓,簡單分析一下熔掺。

分析過程

原表的結(jié)構(gòu):

desc update_test;
+---------+------------------+------+-----+---------+----------------+
| Field   | Type             | Null | Key | Default | Extra          |
+---------+------------------+------+-----+---------+----------------+
| id      | int(11) unsigned | NO   | PRI | NULL    | auto_increment |
| status  | int(11)          | NO   |     | NULL    |                |
| user_id | bigint(20)       | NO   |     | NULL    |                |
| rule_id | tinyint(4)       | NO   |     | NULL    |                |
+---------+------------------+------+-----+---------+----------------+

表中的數(shù)據(jù):


select * from update_test;
+----+--------+---------+---------+
| id | status | user_id | rule_id |
+----+--------+---------+---------+
|  1 |      2 |   10001 |       1 |
|  2 |      1 |   10002 |     100 |
|  3 |      3 |   10003 |     100 |
|  4 |      4 |   10004 |     100 |
|  5 |      1 |   10005 |     100 |
|  6 |      2 |   10006 |       2 |
|  7 |      3 |   10007 |     100 |
|  8 |      2 |   10008 |       1 |
|  9 |      4 |   10009 |     100 |
| 10 |      1 |   10010 |       1 |
+----+--------+---------+---------+

執(zhí)行的update SQL:

update
    update_test
set
    status = 10
    and status in (2, 3)
    and rule_id != 100
    and user_id in (
        10001,
        10002,
        10003,
        10004,
        10005
);
Query OK, 10 rows affected (0.01 sec)
Rows matched: 10  Changed: 10  Warnings: 0

更新的結(jié)果:

mysql> select * from update_test;
+----+--------+---------+---------+
| id | status | user_id | rule_id |
+----+--------+---------+---------+
|  1 |      1 |   10001 |       1 |
|  2 |      0 |   10002 |     100 |
|  3 |      0 |   10003 |     100 |
|  4 |      0 |   10004 |     100 |
|  5 |      0 |   10005 |     100 |
|  6 |      0 |   10006 |       2 |
|  7 |      0 |   10007 |     100 |
|  8 |      0 |   10008 |       1 |
|  9 |      0 |   10009 |     100 |
| 10 |      0 |   10010 |       1 |
+----+--------+---------+---------+
10 rows in set (0.01 sec)

update語句如果需要更新多個(gè)字段,被更新的值需要用逗號(hào)分隔旭愧,而不是and颅筋。從更新結(jié)果看到宙暇,status字段全表被更新為1或者0,推斷MySQL解析器把 and 連接的條件做了 與或運(yùn)算 從而得到了bool值(true為1议泵, false為0)占贫。用sqlparser進(jìn)行試驗(yàn),結(jié)果成立肢簿。

package main

import (
    "fmt"
    "github.com/xwb1989/sqlparser"
)

func main() {
    sql := `update update_test set status = 10 and rule_id != 100 and role_id in (2,3);`
    stmt, _ := sqlparser.Parse(sql)

    //fmt.Printf("%#v\n", stmt)
    u := stmt.(*sqlparser.Update)
    fmt.Println("field: ", u.Exprs[0].Name.Name, "\nexpr :", sqlparser.String(u.Exprs[0].Expr))
}

從結(jié)果中可以看到靶剑,status被設(shè)置為expr里面的值蜻拨。

field:  status 
expr : 10 and rule_id != 100 and role_id in (2, 3)

update語句中含有in條件池充,猜想 in 被解析成或運(yùn)算執(zhí)行的,觀察這條被更新為1的結(jié)果和其原來的數(shù)據(jù)可以得出結(jié)論缎讼。

select * from update_test;
+----+--------+---------+---------+
| id | status | user_id | rule_id |
+----+--------+---------+---------+
|  1 |      2 |   10001 |       1 |  --- 原數(shù)據(jù)   更新條件為(status=2 && rule_id!= 100 && user_id=10001) 此記錄均滿足收夸,猜想成立
+----+--------+---------+---------+
 
 
mysql> select * from update_test;
+----+--------+---------+---------+
| id | status | user_id | rule_id |
+----+--------+---------+---------+
|  1 |      1 |   10001 |       1 |  --- update之后的數(shù)據(jù)
+----+--------+---------+---------+

有的同學(xué)可能要說了,MySQL是有sql_safe_updates 配置的血崭,默認(rèn)關(guān)閉卧惜,只要打開,那么不加條件的update語句就無法執(zhí)行夹纫,就不會(huì)出現(xiàn)這樣的問題了咽瓷,一勞永逸!

show variables like "sql_safe_updates";  -- 查看變量
set sql_safe_updates = 1;                -- session級(jí)別打開

這樣其實(shí)是不行的舰讹,因?yàn)闃I(yè)務(wù)千奇百怪茅姜,有的場(chǎng)景需要不帶條件的update, 而且如果開了,估計(jì)有的ORM就直接用不了了吧月匣,到時(shí)候開發(fā)就該吐槽DBA了...

這是本人的想法钻洒,筆者又去問了一位資深數(shù)據(jù)庫從業(yè)人員,那位大佬說的話非常有哲理锄开,瞬間上升了一個(gè)維度:技術(shù)是用來保障服務(wù)的素标,而不是限制用戶的,如果出現(xiàn)了全表更新萍悴,用flashback修復(fù)头遭。

總結(jié)

想用人眼兜底所有的風(fēng)險(xiǎn)終究是不靠譜的。像這種有風(fēng)險(xiǎn)的操作應(yīng)該走平臺(tái)癣诱,讓平臺(tái)承擔(dān)備份和提醒的工作~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末计维,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子狡刘,更是在濱河造成了極大的恐慌享潜,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,126評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件嗅蔬,死亡現(xiàn)場(chǎng)離奇詭異剑按,居然都是意外死亡疾就,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門艺蝴,熙熙樓的掌柜王于貴愁眉苦臉地迎上來猬腰,“玉大人,你說我怎么就攤上這事猜敢」煤桑” “怎么了?”我有些...
    開封第一講書人閱讀 152,445評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵缩擂,是天一觀的道長鼠冕。 經(jīng)常有香客問我,道長胯盯,這世上最難降的妖魔是什么懈费? 我笑而不...
    開封第一講書人閱讀 55,185評(píng)論 1 278
  • 正文 為了忘掉前任,我火速辦了婚禮博脑,結(jié)果婚禮上憎乙,老公的妹妹穿的比我還像新娘。我一直安慰自己叉趣,他們只是感情好泞边,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評(píng)論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著疗杉,像睡著了一般阵谚。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上乡数,一...
    開封第一講書人閱讀 48,970評(píng)論 1 284
  • 那天椭蹄,我揣著相機(jī)與錄音,去河邊找鬼净赴。 笑死绳矩,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的玖翅。 我是一名探鬼主播翼馆,決...
    沈念sama閱讀 38,276評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼金度!你這毒婦竟也來了应媚?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,927評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤猜极,失蹤者是張志新(化名)和其女友劉穎中姜,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,400評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡丢胚,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評(píng)論 2 323
  • 正文 我和宋清朗相戀三年翩瓜,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片携龟。...
    茶點(diǎn)故事閱讀 37,997評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡兔跌,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出峡蟋,到底是詐尸還是另有隱情坟桅,我是刑警寧澤,帶...
    沈念sama閱讀 33,646評(píng)論 4 322
  • 正文 年R本政府宣布蕊蝗,位于F島的核電站仅乓,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏匿又。R本人自食惡果不足惜方灾,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望碌更。 院中可真熱鬧,春花似錦洞慎、人聲如沸痛单。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽旭绒。三九已至,卻和暖如春焦人,著一層夾襖步出監(jiān)牢的瞬間挥吵,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評(píng)論 1 260
  • 我被黑心中介騙來泰國打工花椭, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留忽匈,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,423評(píng)論 2 352
  • 正文 我出身青樓矿辽,卻偏偏與公主長得像丹允,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子袋倔,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • ORA-00001: 違反唯一約束條件 (.) 錯(cuò)誤說明:當(dāng)在唯一索引所對(duì)應(yīng)的列上鍵入重復(fù)值時(shí)雕蔽,會(huì)觸發(fā)此異常。 O...
    我想起個(gè)好名字閱讀 5,176評(píng)論 0 9
  • ORACLE自學(xué)教程 --create tabletestone ( id number, --序號(hào)usernam...
    落葉寂聊閱讀 1,066評(píng)論 0 0
  • 1. 簡介 1.1 什么是 MyBatis 宾娜? MyBatis 是支持定制化 SQL批狐、存儲(chǔ)過程以及高級(jí)映射的優(yōu)秀的...
    笨鳥慢飛閱讀 5,423評(píng)論 0 4
  • 什么是數(shù)據(jù)庫? 數(shù)據(jù)庫是存儲(chǔ)數(shù)據(jù)的集合的單獨(dú)的應(yīng)用程序前塔。每個(gè)數(shù)據(jù)庫具有一個(gè)或多個(gè)不同的API嚣艇,用于創(chuàng)建缘眶,訪問,管理...
    chen_000閱讀 4,030評(píng)論 0 19
  • 1.首先下載相關(guān)jar包和dll:https://sourceforge.net/projects/jacob-p...
    尋找大海的魚閱讀 1,729評(píng)論 0 0