MySQL 非主鍵索引更新引起的死鎖

表結(jié)構(gòu)如下:

CREATE TABLE `user_item` (
  `id` BIGINT(20) NOT NULL,
  `user_id` BIGINT(20) NOT NULL,
  `item_id` BIGINT(20) NOT NULL,
  `status` TINYINT(4) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_1` (`user_id`,`item_id`,`status`)
) ENGINE=INNODB DEFAULT CHARSET=utf-8

SQL 語句如下:

update user_item set status=1 where user_id=? and item_id=?

原因分析

MySQL 的事務(wù)支持與存儲引擎有關(guān)弹沽,MyISAM 不支持事務(wù)牛欢,INNODB 支持事務(wù)风题,更新時采用的是行級鎖像棘。這里采用的是 INNODB 做存儲引擎,意味著會將 update 語句做為一個事務(wù)來處理疙筹。前面提到行級鎖必須建立在索引的基礎(chǔ)桨昙,這條更新語句用到了索引 idx_1,所以這里肯定會加上行級鎖

行級鎖并不是直接鎖記錄腌歉,而是鎖索引,如果一條 SQL 語句用到了主鍵索引齐苛,mysql 會鎖住主鍵索引翘盖;如果一條語句操作了非主鍵索引,mysql 會先鎖住非主鍵索引凹蜂,再鎖定主鍵索引

這個 update 語句會執(zhí)行以下步驟:
1馍驯、由于用到了非主鍵索引阁危,首先需要獲取 idx_1 上的行級鎖
2、緊接著根據(jù)主鍵進(jìn)行更新汰瘫,所以需要獲取主鍵上的行級鎖
3狂打、更新完畢后,提交混弥,并釋放所有鎖趴乡。

如果在步驟 1 和 2 之間突然插入一條語句:update user_item .....where id=? and user_id=?,這條語句會先鎖住主鍵索引蝗拿,然后鎖住 idx_1

蛋疼的情況出現(xiàn)了晾捏,一條語句獲取了 idx_1 上的鎖,等待主鍵索引上的鎖哀托;另一條語句獲取了主鍵索引上的鎖惦辛,等待 idx_1 上的鎖,這樣就出現(xiàn)了死鎖

解決方法

只要讓更新操作中帶有主鍵即可仓手,也就是讓獲取鎖的順序一致即可:

  1. 先獲取需要更新的記錄的主鍵
select id from user_item where user_id=? and item_id=?
  1. 逐條更新
select id from user_item where user_id=? and item_id=?  
for (Long id : idList) {  
    userItemDAO.updateStatus(id, userId, 1);  
}
update user_item set status=? where id=? and user_id=?
  1. 這樣貌似解決了胖齐,都是對單條進(jìn)行操作,都是先獲取主鍵上的鎖嗽冒,再獲取 idx_1 上的鎖
    不過這個解決方案與先前的更新語句不一樣呀伙,先前的更新語句(update user_item set status=1 where user_id=? and item_id=?)對所有記錄的更新在一個事務(wù)中,采用循環(huán)更新后并不在同一個事務(wù)中辛慰,所以在 for 循環(huán)外面還得開一個事務(wù)区匠。偽代碼:
public Object doInTransaction(Transaction t) {
    try {
        for (Long id : idList) {
            userItemDAO.updateStatus(id, userId, 1);
        }
        return null;
    } catch (DAOException e) {
        t.rollback();
    } catch (Exception e) {
        r.rollback();
    }
}

總結(jié)

在采用 INNODB 的 MySQL 中,更新操作默認(rèn)會加行級鎖帅腌,行級鎖是基于索引的驰弄,在分析死鎖之前需要查詢一下 mysql 的執(zhí)行計劃,看看是否用到了索引速客,用到了哪個索引戚篙,對于沒有用索引的操作會采用表級鎖。如果操作用到了主鍵索引會先在主鍵索引上加鎖溺职,然后在其他索引上加鎖岔擂,否則加鎖順序相反。在并發(fā)度高的應(yīng)用中浪耘,批量更新一定要帶上記錄的主鍵乱灵,優(yōu)先獲取主鍵上的鎖,這樣可以減少死鎖的發(fā)生

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末七冲,一起剝皮案震驚了整個濱河市痛倚,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌澜躺,老刑警劉巖蝉稳,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件抒蚜,死亡現(xiàn)場離奇詭異,居然都是意外死亡耘戚,警方通過查閱死者的電腦和手機(jī)嗡髓,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來收津,“玉大人饿这,你說我怎么就攤上這事∨蠼兀” “怎么了蛹稍?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長部服。 經(jīng)常有香客問我唆姐,道長,這世上最難降的妖魔是什么廓八? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任奉芦,我火速辦了婚禮,結(jié)果婚禮上剧蹂,老公的妹妹穿的比我還像新娘声功。我一直安慰自己,他們只是感情好宠叼,可當(dāng)我...
    茶點故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布先巴。 她就那樣靜靜地躺著,像睡著了一般冒冬。 火紅的嫁衣襯著肌膚如雪伸蚯。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天简烤,我揣著相機(jī)與錄音剂邮,去河邊找鬼。 笑死横侦,一個胖子當(dāng)著我的面吹牛挥萌,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播枉侧,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼引瀑,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了榨馁?” 一聲冷哼從身側(cè)響起伤疙,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后徒像,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡蛙讥,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年锯蛀,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片次慢。...
    茶點故事閱讀 39,722評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡旁涤,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出迫像,到底是詐尸還是另有隱情劈愚,我是刑警寧澤,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布闻妓,位于F島的核電站菌羽,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏由缆。R本人自食惡果不足惜注祖,卻給世界環(huán)境...
    茶點故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望均唉。 院中可真熱鬧是晨,春花似錦、人聲如沸舔箭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽层扶。三九已至箫章,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間怒医,已是汗流浹背炉抒。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留稚叹,地道東北人焰薄。 一個月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像扒袖,于是被迫代替她去往敵國和親塞茅。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,614評論 2 353

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

  • 《高性能MySQL》&《MySQL技術(shù)內(nèi)幕 InnoDB存儲引擎》筆記 第一章 MySQL架構(gòu)與歷史 MySQL的...
    xiaogmail閱讀 12,766評論 0 39
  • 轉(zhuǎn)載自http://blog.csdn.net/aesop_wubo/article/details/828621...
    窩偶韭剩狂奔閱讀 2,036評論 0 5
  • 結(jié)婚七年半了野瘦,二寶還有不到三個月就要降臨了,當(dāng)初鐵了心只要一個,帶老大的心酸歷程到死不能忘鞭光,但是政策放開后覺得多一...
    啦啦對閱讀 212評論 0 0
  • 走在立春過后的街頭吏廉,空氣中已經(jīng)有春暖的氣息。你大概會說零下十度不是冰碴子味嗎惰许?不席覆,作為一個北方人(請對方辯友繼續(xù)自...
    花咯閱讀 304評論 0 1
  • 1.強調(diào)明天接學(xué)生的具體細(xì)節(jié)⌒诼颍考試時間是上午9點佩伤,開考前20分鐘進(jìn)入教室,10:30語文結(jié)束晦毙,每層樓有相應(yīng)的衛(wèi)生間...
    瑕疵點點閱讀 151評論 0 0