如何判斷數據庫死鎖和數據庫死鎖的處理方式

可參考: 數據庫中死鎖那些事兒 https://blog.csdn.net/eseaqyq/article/details/7795023
MySQL InnoDB死鎖及死鎖檢測(四)http://www.ywnds.com/?p=4949

二、MySQL InnoDB死鎖檢測
1) 儘量不出現死鎖

在代碼層調整SQL操作順序,或者縮短事務長度,以避免出現死鎖。

2) 碰撞檢測

當死鎖出現時,Innodb會主動探知到死鎖,並回滾了某一苦苦等待的事務。問題來了,Innodb是怎麼探知死鎖的?

核心就是數據庫會把事務單元鎖維持的鎖和它所等待的鎖都記錄下來,Innodb提供了wait-for graph算法來主動進行死鎖檢測,每當加鎖請求無法立即滿足需要進入等待時,wait-for graph算法都會被觸發。當數據庫檢測到兩個事務不同方向地給同一個資源加鎖(產生循序),它就認爲發生了死鎖,觸發wait-for graph算法。比如,事務1給A加鎖,事務2給B加鎖,同時事務1給B加鎖(等待),事務2給A加鎖就發生了死鎖。那麼死鎖解決辦法就是終止一邊事務的執行即可,這種效率一般來說是最高的,也是主流數據庫採用的辦法。

Innodb目前處理死鎖的方法就是將持有最少行級排他鎖的事務進行回滾。這也是相對比較簡單的死鎖回滾方式。死鎖發生以後,只有部分或者完全回滾其中一個事務,才能打破死鎖。對於事務型的系統,這是無法避免的,所以應用程序在設計必須考慮如何處理死鎖。大多數情況下只需要重新執行因死鎖回滾的事務即可。

wait-for graph原理

我們怎麼知道圖中四輛車是死鎖的?

MySQL InnoDB死鎖及死鎖檢測(四)

他們相互等待對方的資源,而且形成環路!我們將每輛車看爲一個節點,當節點1需要等待節點2的資源時,就生成一條有向邊指向節點2,最後形成一個有向圖。我們只要檢測這個有向圖是否出現環路即可,出現環路就是死鎖!這就是wait-for graph算法。

MySQL InnoDB死鎖及死鎖檢測(四)

Innodb將各個事務看爲一個個節點,資源就是各個事務佔用的鎖,當事務1需要等待事務2的鎖時,就生成一條有向邊從1指向2,最後行成一個有向圖。

3)等鎖超時

死鎖超時也是一種常見的做法,就是等待鎖持有時間,如果說一個事務持有鎖超過設置時間的話,就直接拋出一個錯誤,參數innodb_lock_wait_timeout用來設置超時時間。如果有些用戶使用哪種超長的事務,你就需要把鎖超時時間大於事務執行時間。在這種情況下這種死鎖超時的方式就會導致每一個死鎖超時被發現的時間是無法接受的。

不要太擔心死鎖,你可能會在MySQL error log中看到關於死鎖的警告信息,或者在show engine InnoDB status輸出中看到它。儘管看起來是一個可怕的名字,但deadlock不是一個嚴重的問題,對於InnoDB來說,通常不需要做任何糾正操作。當兩個事務開始修改多個表時,如果訪問表的順序不同,會出現互相等待對方釋放鎖,然後才能繼續處理的情況。MySQL會立刻發現這種情況並且終止較小的事務,允許其他的事務執行。

你的應用程序的確需要錯誤處理邏輯來重啓該事務。當你重新執行相同的SQL語句時,原來的時間問題不再適用:要麼其他的事務已經執行完成,這樣你就可以執行事務了,要麼其他的事務還在處理過程中,你的事務只能等它結束。

如果不斷警告發生死鎖,你可能要review你的應用程序源代碼,調整SQL操作順序,或者縮短事務長度。你可以啓用innodb_print_all_deadlocks選項,把deadlock信息記錄到MySQL的錯誤日誌總,而不是僅僅通過show engine innob status查看。

鎖跟索引的關係

這時我們要注意到,money表雖然沒有添加索引,但是InnoDB存儲引擎會使用隱式的主鍵來進行鎖定。對於沒有索引或主鍵的表來說,那麼MySQL會給整張表的所有數據行的加行鎖。這裏聽起來有點不可思議,但是當sql運行的過程中,MySQL並不知道哪些數據行是id=1(沒有索引嘛),如果一個條件無法通過索引快速過濾,存儲引擎層面就會將所有記錄加鎖後返回,再由MySQL Server層進行過濾。但在實際使用過程當中,MySQL做了一些改進,在MySQL Server過濾條件,發現不滿足後,會調用unlock_row方法,把不滿足條件的記錄釋放鎖 (違背了二段鎖協議的約束)。這樣做,保證了最後只會持有滿足條件記錄上的鎖,但是每條記錄的加鎖操作還是不能省略的。可見即使是MySQL,爲了效率也是會違反規範的。這種情況同樣適用於MySQL的默認隔離級別RC。所以對一個數據量很大的表做批量修改的時候,如果無法使用相應的索引,MySQL過濾數據的的時候特別慢,就會出現雖然沒有修改某些行的數據,但是它們還是被鎖住了的現象。

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