您好,登錄后才能下訂單哦!
數據越來越和我們的生活離不開,數據在生命周期的各個階段有著不同的痛點和需求以及特殊場景。
CURD是數據的四大基本需求:寫入,更新,讀取,刪除.
今天,來談一談死鎖問題
死鎖是高并發下MySQL不可回避的一個問題。
這句話可以引申四個問題:
1.什么是死鎖?
2.MySQL什么時候會檢測死鎖?
3.數據庫系統如何處理死鎖?
4.有哪些典型的高并發死鎖場景?
1.我們先來看看什么是死鎖。
在《數據庫系統實現》第八章第二節這樣定義死鎖
并發執行的事務由于競爭資源而到達一個存在死鎖的狀態:若干事務的每一個事務都在等待被其他事務占用的資源,因而每個事務都不能取得進展。
這個描述貌似很拗口,我們舉兩個例子來形象化認識一下:
1.兩位木匠釘地板,一位只握一把斧頭,而另一位沒有榔頭,卻有釘子
2.堵車現象
看完死鎖的定義描述和形象化認識,那對于MySQL,什么時候會進行死鎖檢測?
2.MySQL的死鎖檢測和回滾
這里談論MySQL的死鎖檢測,目前僅討論InnoDB的處理,暫不涉及MyRocks的死鎖檢測處理。
當InnoDB事務嘗試獲取(請求)加一個鎖,并且需要等待時,InnoDB會進行死鎖檢測.
正常的流程如下:
1.InnoDB的初始化一個事務,當事務嘗試獲取(請求)加一個鎖,并且需要等待時(wait_lock),innodb會開始進行死鎖檢測(deadlock_mark)
2.進入到lock_deadlock_check_and_resolve ,名字很明顯了,要檢測死鎖和解決死鎖
3.檢測死鎖過程中,也是有計數器來進行限制的
4.死鎖檢測的邏輯之一是等待圖的處理過程,如果通過鎖的信息和事務等待鏈構造出一個圖,如果圖中出現回路,就認為發生了死鎖。
5.死鎖的回滾,內部代碼的處理邏輯之一是比較undo的數量
3.數據庫系統如何處理死鎖
我們回頭繼續看《數據庫系統實現》里面提到的死鎖處理
1.超時死鎖檢測:當存在死鎖時,想所有事務都能同時繼續執行通常是不可能的,因此,至少一個事務必須中止并重新開始。超時是最直接的辦法,對超出活躍時間的事務進行限制和回滾
2.等待圖:等待圖的實現,是可以表明哪些事務在等待其他事務持有的鎖,可以在數據庫的死鎖檢測里面加上這個機制來進行檢測是否有環的形成。
3.通過元素排序預防死鎖:這個想法很美好,但現實很殘酷,通常都是發現死鎖后才去想辦法解決死鎖的原因
4.通過時間戳檢測死鎖:對每個事務都分配一個時間戳,根據時間戳來進行回滾策略。
這里貼一下等待圖的示例
4.有哪些典型的高并發死鎖場景?
1.秒殺場景,每個秒殺都是針對同一行的活躍事務,源源不斷的事務發現自己加鎖的那一行已經被人鎖了,這時候InnoDB會進入一個蛋疼的沒必要的死鎖檢測,后續給大家講講怎么解決
2.使用二級索引去高并發更新二級索引記錄(很拗口吧?),MySQL的索引計劃不是100%準確的,我手上有case在并發更新不同記錄的時候,因為索引計劃走錯了,導致某一個事務用了二級索引讀記錄,另外一個事務用主鍵來讀記錄,進而產生了死鎖,這個案例后續也會整理出來。
最后 MySQL的源碼如何進行死鎖檢測和處理?
這個問題是后續的關鍵,但沒整理完,先歇一歇...
建議先讀一讀上一篇《InnoDB事務結構體代碼變量列表》,因為死鎖是在活躍事務等待鎖的情況下才會去檢測,要先去了解InnoDB事務結構體的trx_lock_t
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。