標籤:定義 ... 死結 res adl 資料 如何 技術 ima
資料越來越和我們的生活離不開,資料在生命週期的各個階段有著不同的痛點和需求以及特殊情境。
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
談談MySQL死結 一