MySQL Update批量更新死鎖問題排查

MySQL Update批量更新死鎖問題排查

背景

業務中有兩個不同的業務,更新同一批數據時出現死鎖問題,sql語句如下

update test set a= 1 where name = 'test';
update test set b = 2 where name = 'test' and time >0;
-- 這裏的name是一個普通的索引

頻繁出現死鎖

鎖分析

update鎖的執行過程:

  1. 首先根據where條件查出符合條件的數據,這個查詢是一條一條查詢的
  2. Innodb引擎支持行鎖,纔會出現死鎖,表鎖不會出現死鎖
  3. MySQL會首先取出來第一條符合的數據,並同時對這個數據加上共享鎖
  4. 然後再對這個數據進行S鎖升級到X鎖

數據加鎖的過程(如果sql沒有用到索引,會加表鎖):

  1. 首先查詢這個數據的索引,如果是非主鍵索引,那麼會先給索引加鎖
  2. 然後會根據索引查找對應的主鍵,進行主鍵聚簇索引加鎖

可能性分析

  1. 增加time條件導致的加鎖異常
    我首先猜測,是不是因爲第二條sql語句中加了一個非索引條件,導致索引加鎖順序發生變化,先對主鍵索引進行加鎖,然後再對普通索引進行加鎖,後來查詢資料,說加鎖順序是一定的,一定是先加普通索引的鎖,所以這個排除了
  2. 多線程併發問題導致S鎖異常
    兩個事務同時對一條數據進行更新的時候(這個是否爲併發有待驗證),兩個update語句都拿到了數據的S鎖,但是升級X鎖的時候,出現問題,因爲S鎖升級X鎖,在隔離等級是RC的情況下,瞭解到必須等所有的S鎖解開,才能S鎖升X鎖,所以兩個事務相互等待,死鎖了。

經過分析,第二種可能性更大,但是系統是頻繁報錯,所以後續還會繼續排查

結果處理

MySQL之上加了一層redis緩存鎖,防止多個腳本同時更新一個數據,如果有其他的解決方法,希望大家評論回覆下

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章