【MySQL】死鎖及實例說明

死鎖是指兩個或者多個事務在同一資源上相互佔用,並請求鎖定對方佔用的資源,從而導致惡性循環的現象。當多個事務試圖以不同的順序鎖定資源時,就可能會產生死鎖。多個事務同時鎖定同一個資源時,也會產生死鎖。例如,設想下面兩個事務同時處理StockPrice表:

事務1:

START TRANSACTION;
UPDATE StockPrice SET close = 45.50 WHERE stock_id = 4 and date = '2002-05-01';
UPDATE StockPrice SET close = 19.80 WHERE stock_id = 3 and date = '2002-05-02';
COMMIT;

事務2:

START TRANSACTION;
UPDATE StockPrice SET high = 20.12 WHERE stock_id = 3 and date = '2002-05-02';
UPDATE StockPrice SET high = 47.20 WHERE stock_id = 4 and date = '2002-05-01';
COMMIT;

如果湊巧,兩個事務都執行了第一條UPDATE語句,更新了一行數據,同時也鎖定了該行數據,接着每個事務都嘗試去執行第二條UPDATE語句,卻發現該行已經被對方鎖定,然後兩個事務都等待對方釋放鎖,同時又持有對方需要的鎖,則陷入死循環。除非有外部因素介入纔可能解除死鎖。

爲了解決這種問題,數據庫系統實現了各種死鎖檢測和死鎖超時機制。越複雜的系統,比如InnoDB存儲引擎,越能檢測到死鎖的循環依賴,並立即返回一個錯誤。這種解決方式很有效,否則死鎖會導致出現非常慢的查詢。還有一種解決方式,就是當查詢的時間達到鎖等待超時的設定後放棄鎖請求,這種方式通常來說不太好。InnoDB目前處理死鎖的方法是,將持有最少行級排他鎖的事務進行回滾(這是相對比較簡單的死鎖回滾算法)。

鎖的行爲和順序是和存儲引擎相關的。以同樣的順序執行語句,有些存儲引擎會產生死鎖,有些則不會。死鎖的產生有雙重原因:有些是因爲真正的數據衝突,這種情況通常很難避免,但有些則完全是由於存儲引擎的實現方式導致的。

死鎖發生以後,只有部分或者完全回滾其中一個事務,才能打破死鎖。對於事務型的系統,這是無法避免的,所以應用程序在設計時必須考慮如何處理死鎖。大多數情況下只需要重新執行因死鎖回滾的事務即可。

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