Mysql行鎖機(jī)制引發(fā)的血案

最近在開發(fā)中使用到了多線程對(duì)同個(gè)表進(jìn)行讀寫操作楼镐,由于數(shù)據(jù)庫基礎(chǔ)渣渣馆截,寫完代碼后程序跑起來出現(xiàn)了死鎖抖锥。于是對(duì)日志進(jìn)行分析跟蹤宵喂,發(fā)現(xiàn)在執(zhí)行以下SQL時(shí)出現(xiàn)死鎖:

UPDATE linkgoo_message_queue SET state = 3 where state = 2;

很明顯在執(zhí)行上述SQL時(shí)糠赦,由于某個(gè)原因?qū)е卤韑inkgoo_message_queue被鎖或者表中相關(guān)記錄被鎖。那么問題來了锅棕,Mysql中Update的時(shí)候會(huì)怎么去加鎖呢拙泽?

網(wǎng)上查找資料并進(jìn)行試驗(yàn)后得到如下結(jié)論:

1.Mysql行鎖除了會(huì)鎖記錄之外,還有可能對(duì)索引加鎖裸燎,這取決于你的SQL寫法顾瞻;

2.UPDATE數(shù)據(jù)時(shí),若條件中包含主鍵德绿,那么只鎖該主鍵對(duì)應(yīng)的記錄荷荤;(注:網(wǎng)上找到的資料還提及:若操作了某個(gè)索引字段,比如 SET state=3 移稳,state為索引字段蕴纳,那么state這個(gè)索引也會(huì)被鎖上。但通過實(shí)驗(yàn)證明个粱,若兩條SQL條件中都存在主鍵古毛,且操作了相同的索引字段,是不會(huì)引發(fā)資源等待的都许!如果第一條SQL以主鍵為條件操作了索引字段稻薇,第二條SQL以索引字段為條件進(jìn)行UPDATE嫂冻,那么第二條SQL需要等待直到第一條SQL釋放鎖資源

3.UPDATE數(shù)據(jù)時(shí),若條件中不包含主鍵但含有索引字段颖低,那么Mysql會(huì)先對(duì)索引加鎖絮吵,再對(duì)受影響的記錄加鎖。且如果SQL中還對(duì)索引字段進(jìn)行操作忱屑,那么還會(huì)對(duì)該索引字段追加鎖蹬敲。(注意加鎖是有順序的!正是因?yàn)檫@樣才導(dǎo)致的死鎖

4.通過實(shí)驗(yàn)證明莺戒,對(duì)索引加鎖伴嗡,是對(duì)整個(gè)字段加鎖,而不是對(duì)索引的某個(gè)值(比如state=3)加鎖从铲。

通過上述的信息瘪校,我們?cè)賮矸治鲆幌逻@條SQL:

UPDATE linkgoo_message_queue SET state = 3 where state = 2;

首先Mysql會(huì)對(duì)state這個(gè)索引加鎖,然后再對(duì)state=2的所有記錄加鎖名段。由于存在SET state = 3阱扬,還會(huì)對(duì)state這個(gè)索引進(jìn)行加鎖,但之前已經(jīng)加過了伸辟,不會(huì)再重復(fù)加麻惶。

OK,我們?cè)倩仡櫼幌隆秵纹瑱C(jī)原理與嵌入式系統(tǒng)設(shè)計(jì)》里邊(別問我為什么是這本書,我會(huì)告訴你我是自動(dòng)化專業(yè)出身的萬金油嗎信夫?)對(duì)死鎖的定義:指兩個(gè)或兩個(gè)以上的進(jìn)程在執(zhí)行過程中窃蹋,由于競(jìng)爭資源或者由于彼此通信而造成的一種阻塞的現(xiàn)象。

對(duì)于上邊的SQL静稻,由于其占用了state索引和相關(guān)的數(shù)據(jù)庫記錄警没,倘若要在并發(fā)條件下發(fā)生死鎖,那么若存在有線程先把記錄給鎖了振湾,再要鎖state索引杀迹,那么就有可能出現(xiàn)死鎖。

重新梳理代碼和業(yè)務(wù)邏輯押搪,在處理完message后树酪,會(huì)根據(jù)message.id對(duì)message的state進(jìn)行更新。問題到此已經(jīng)很明顯了嵌言,執(zhí)行UPDATE linkgoo_message_queue SET state = 3 where state = 2時(shí)嗅回,若state索引已經(jīng)鎖了,但還未對(duì)記錄進(jìn)行上鎖摧茴。此時(shí)根據(jù)message.id 去更新state,會(huì)對(duì)id=xxx這條記錄進(jìn)行上鎖绵载,并等待state索引的鎖釋放。而第一條SQL進(jìn)入記錄上鎖階段發(fā)現(xiàn)記錄已經(jīng)被鎖了,進(jìn)入了死循環(huán)發(fā)生死鎖娃豹。

那么上邊的問題怎么去解決呢焚虱?

在Mysql中UPDATE時(shí)不要直接將索引字段放到條件中進(jìn)行篩選,應(yīng)該采用SELECT先找出需要修改的數(shù)據(jù)懂版,再逐條對(duì)數(shù)據(jù)進(jìn)行UPDATE鹃栽。注意需要考慮如何讓SELECT出來的記錄在修改前還是查詢時(shí)的狀態(tài),而不是被其他線程UPDATE躯畴。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末民鼓,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子蓬抄,更是在濱河造成了極大的恐慌丰嘉,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,723評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件嚷缭,死亡現(xiàn)場(chǎng)離奇詭異饮亏,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)阅爽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門路幸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人付翁,你說我怎么就攤上這事简肴。” “怎么了胆敞?”我有些...
    開封第一講書人閱讀 152,998評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵着帽,是天一觀的道長杂伟。 經(jīng)常有香客問我移层,道長,這世上最難降的妖魔是什么赫粥? 我笑而不...
    開封第一講書人閱讀 55,323評(píng)論 1 279
  • 正文 為了忘掉前任观话,我火速辦了婚禮,結(jié)果婚禮上越平,老公的妹妹穿的比我還像新娘频蛔。我一直安慰自己,他們只是感情好秦叛,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,355評(píng)論 5 374
  • 文/花漫 我一把揭開白布晦溪。 她就那樣靜靜地躺著,像睡著了一般挣跋。 火紅的嫁衣襯著肌膚如雪三圆。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,079評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音舟肉,去河邊找鬼修噪。 笑死,一個(gè)胖子當(dāng)著我的面吹牛路媚,可吹牛的內(nèi)容都是我干的黄琼。 我是一名探鬼主播,決...
    沈念sama閱讀 38,389評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼整慎,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼脏款!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起裤园,我...
    開封第一講書人閱讀 37,019評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤弛矛,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后比然,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體丈氓,經(jīng)...
    沈念sama閱讀 43,519評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡是目,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,971評(píng)論 2 325
  • 正文 我和宋清朗相戀三年补履,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了镊讼。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片猿挚。...
    茶點(diǎn)故事閱讀 38,100評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡焕参,死狀恐怖勇蝙,靈堂內(nèi)的尸體忽然破棺而出畜挨,到底是詐尸還是另有隱情蝌蹂,我是刑警寧澤蓖墅,帶...
    沈念sama閱讀 33,738評(píng)論 4 324
  • 正文 年R本政府宣布库倘,位于F島的核電站,受9級(jí)特大地震影響论矾,放射性物質(zhì)發(fā)生泄漏教翩。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,293評(píng)論 3 307
  • 文/蒙蒙 一贪壳、第九天 我趴在偏房一處隱蔽的房頂上張望饱亿。 院中可真熱鬧,春花似錦闰靴、人聲如沸彪笼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽配猫。三九已至,卻和暖如春杏死,著一層夾襖步出監(jiān)牢的瞬間泵肄,已是汗流浹背佳遣。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評(píng)論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留凡伊,地道東北人零渐。 一個(gè)月前我還...
    沈念sama閱讀 45,547評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像系忙,于是被迫代替她去往敵國和親诵盼。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,834評(píng)論 2 345

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