記一次線上sqlserver數據的死鎖問題

最近接手了公司一個比較老的酒店中央預定系統的對接維護工作,發現訂單經常會報sqlserver事務死鎖。

於是便決定排查一下倒是是哪裏引起了這個問題,

1.查看問題訂單:發現問題訂單淘寶渠道過來的但攜程的訂單基本沒有這個問題,分析了出問題的訂單之後發現淘寶過來出問題的訂單經常是統一酒店同一時間多筆訂單一起下單時會有死鎖問題。

2.檢查系統錯誤日誌:發現錯誤日誌都在最後調用.net的ws接口下單時才報的錯誤(中央預定系統是.net的)。並不是我們這邊做的對接渠道的java系統的代碼問題。

3:檢查.net接口系統:無奈之下只好反編譯了.net的代碼,發現接口代碼中開啓事務的只有對訂單的insert操作,因爲單獨的insert操作不可能引發死鎖。所以判斷這張表上肯定存在觸發器,進行了其他操作。於是將問題縮小到了訂單表中。

4:查看訂單表和sqlserver死鎖日誌:

從死鎖日誌,大致分析 線程1先修改完了表a所以拿到了X鎖 ,然後線程2也想修改表a的記錄所以準備加U鎖,但是記錄被線程1修改了所以無法加上u鎖進入了等待,而線程3想要對記錄加S鎖進行讀取卻發現被線程2的IX堵塞了,線程4和線程1也是在同一步select 操作中發生了等待,;

觀察訂單表發現訂單表果然有一個insert的觸發器,觸發器中首先是對錶a進行了update

也就是錯誤日誌中線程2等待的地方,之後便是其他線程等待的查詢,

於是得出結論線程1先修改了表a,然後線程2修改表a進行等待,但是線程1卻因爲線程2的操作進入了等待。查詢資料後發現原來sqlserver在insert之後會對錶和頁添加ix鎖,對插入記錄添加x鎖。

5.錯誤重現

對錶進行insert操作

發現sqlsever在insert 之後會對錶和頁對象加ix鎖,對索引字段的key加x鎖,

然後執行剛剛發生死鎖的查詢

到此發現查詢是29行對(293f。。)key添加的s鎖 ,正好會和insert 後15行對(293f。。)key添加的x鎖,兩個key正好是同一個key,而這個key已經加了x鎖,頁已經加了ix鎖。所以發生衝突。死鎖日誌顯示s鎖等待ix鎖。

 

6。結果問題

分析:因爲老系統代碼過於耦合修改困難。在分析過程後得出只要讓預定同一酒店,同一房型,同一天的訂單。串行化執行。不在表a堆積u鎖和X鎖。就可以避免死鎖發生,避免下訂單失敗的損失。

結果:對老接口進行重新封裝。用redis的setnx命令保證同一時間內調用下單接口:預定同一酒店,同一房型,同一天的訂單的請求依次執行:拿到鎖的請求才能下單。其他請求進行循環知道拿到redis鎖

 

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