<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
生產環境出現死鎖流水,通過檢視死鎖紀錄檔,看到造成死鎖的是兩條一樣的update語句(只有where條件中的值不同),
如下:
UPDATE test_table SET `status` = 1 WHERE `trans_id` = 'xxx1' AND `status` = 0; UPDATE test_table SET `status` = 1 WHERE `trans_id` = 'xxx2' AND `status` = 0;
一開始比較費解,通過大量查詢跟學習後,分析出了死鎖形成的具體原理,特分享給大家,希望能幫助到遇到同樣問題的朋友。
因為MySQL
知識點較多,這裡對很多名詞不進行過多介紹,有興趣的朋友,可以後續進行專項深入學習。
*** (1) TRANSACTION: TRANSACTION 791913819, ACTIVE 0 sec starting index read, thread declared inside InnoDB 4999 mysql tables in use 3, locked 3 LOCK WAIT 4 lock struct(s), heap size 1184, 3 row lock(s) MySQL thread id 462005230, OS thread handle 0x7f55d5da3700, query id 2621313306 x.x.x.x test_user Searching rows for update UPDATE test_table SET `status` = 1 WHERE `trans_id` = 'xxx1' AND `status` = 0; *** (1) WAITING FOR THIS LOCK TO BE GRANTED: RECORD LOCKS space id 110 page no 39167 n bits 1056 index `idx_status` of table `test`.`test_table` trx id 791913819 lock_mode X waiting Record lock, heap no 495 PHYSICAL RECORD: n_fields 2; compact format; info bits 0 *** (2) TRANSACTION: TRANSACTION 791913818, ACTIVE 0 sec starting index read, thread declared inside InnoDB 4999 mysql tables in use 3, locked 3 5 lock struct(s), heap size 1184, 4 row lock(s) MySQL thread id 462005231, OS thread handle 0x7f55cee63700, query id 2621313305 x.x.x.x test_user Searching rows for update UPDATE test_table SET `status` = 1 WHERE `trans_id` = 'xxx2' AND `status` = 0; *** (2) HOLDS THE LOCK(S): RECORD LOCKS space id 110 page no 39167 n bits 1056 index `idx_status` of table `test`.`test_table` trx id 791913818 lock_mode X Record lock, heap no 495 PHYSICAL RECORD: n_fields 2; compact format; info bits 0 *** (2) WAITING FOR THIS LOCK TO BE GRANTED: RECORD LOCKS space id 110 page no 41569 n bits 88 index `PRIMARY` of table `test`.`test_table` trx id 791913818 lock_mode X locks rec but not gap waiting Record lock, heap no 14 PHYSICAL RECORD: n_fields 30; compact format; info bits 0 *** WE ROLL BACK TRANSACTION (1)
簡要分析下上邊的死鎖紀錄檔:
CREATE TABLE `test_table` ( `id` int(11) NOT NULL AUTO_INCREMENT, `trans_id` varchar(21) NOT NULL, `status` int(11) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `uniq_trans_id` (`trans_id`) USING BTREE, KEY `idx_status` (`status`) USING BTREE ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8
通過表結構可以看出,trans_id
列上有一個唯一索引uniq_trans_id
,status
列上有一個普通索引idx_status
,id列為主鍵索引 PRIMARY
。
InnoDB引擎中有兩種索引:
主鍵索引 PRIMARY
就是聚簇索引,葉子節點中會儲存行資料。uniq_trans_id
索引和idx_status
索引為輔助索引,葉子節點中儲存的是主鍵值,也就是id列值。
當我們通過輔助索引查詢行資料時,先通過輔助索引找到主鍵id,再通過主鍵索引進行二次查詢(也叫回表),最終找到行資料。
通過看執行計劃,可以發現,update語句用到了索引合併,也就是這條語句既用到了 uniq_trans_id
索引,又用到了 idx_status
索引,Using intersect(uniq_trans_id,idx_status)
的意思是通過兩個索引獲取交集。
MySQL5.0之前,一個表一次只能使用一個索引,無法同時使用多個索引分別進行條件掃描。但是從5.1開始,引入了 index merge
優化技術,對同一個表可以使用多個索引分別進行條件掃描。
如執行計劃中的語句:
UPDATE test_table SET `status` = 1 WHERE `trans_id` = '38' AND `status` = 0 ;
MySQL會根據 trans_id = ‘38’
這個條件,利用 uniq_trans_id
索引找到葉子節點中儲存的id值;同時會根據 status = 0
這個條件,利用 idx_status
索引找到葉子節點中儲存的id值;然後將找到的兩組id值取交集,最終通過交集後的id回表,也就是通過 PRIMARY 索引找到葉子節點中儲存的行資料。
這裡可能很多人會有疑問了,uniq_trans_id
已經是一個唯一索引了,通過這個索引最終只能找到最多一條資料,那MySQL優化器為啥還要用兩個索引取交集,再回表進行查詢呢,這樣不是多了一次 idx_status
索引查詢的過程麼。我們來分析一下這兩種情況執行過程。
第一種 只用uniq_trans_id索引 :
trans_id = ‘38’
查詢條件,利用uniq_trans_id
索引找到葉子節點中儲存的id值;status = 0
條件對找到的行資料進行過濾。第二種 用到索引合併 Using intersect(uniq_trans_id,idx_status)
:
trans_id = ‘38’
查詢條件,利用 uniq_trans_id
索引找到葉子節點中儲存的id值;status = 0
查詢條件,利用 idx_status
索引找到葉子節點中儲存的id值;上邊兩種情況,主要區別在於,第一種是先通過一個索引把資料找到後,再用其它查詢條件進行過濾;第二種是先通過兩個索引查出的id值取交集,如果取交集後還存在id值,則再去回表將資料取出來。
當優化器認為第二種情況執行成本比第一種要小時,就會出現索引合併。(生產環境流水錶中 status = 0
的資料非常少,這也是優化器考慮用第二種情況的原因之一)。
為什麼用了 index_merge
就死鎖了
上面簡要畫了一下兩個update事務加鎖的過程,從圖中可以看到,在idx_status
索引和 PRIMARY (聚簇索引) 上都存在重合交叉的部分,這樣就為死鎖造成了條件。
如,當遇到以下時序時,就會出現死鎖:
事務1等待事務2釋放鎖,事務2等待事務1釋放鎖,這樣就造成了死鎖。
MySQL檢測到死鎖後,會自動回滾代價更低的那個事務,如上邊的時序圖中,事務1持有的鎖比事務2少,則MySQL就將事務1進行了回滾。
trans_id
,將資料查詢出來後,在程式碼層面判斷 status 狀態是否為0;force index(uniq_trans_id)
強制查詢語句使用 uniq_trans_id
索引;idx_status
索引或者建一個包含這倆列的聯合索引;index merge
優化關閉。到此這篇關於MySQL 優化 index merge引起的死鎖分析的文章就介紹到這了,更多相關MySQL 優化 index merge內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45