MySQL死鎖接觸少,但面試又經常被問到怎麼辦? 最近有小伙伴在面試的時候,被問了MySQL死鎖,如何解決? 雖然也回答出來了,但是不夠全面體系化, 所以,小北給大家做一下系統化、體系化的梳理,幫助大家在面試過程中能夠脫穎而出,拿到自己心儀的Offer 插播一條:如果你近期準備面試跳槽,建議在htt ...
MySQL死鎖接觸少,但面試又經常被問到怎麼辦?
最近有小伙伴在面試的時候,被問了MySQL死鎖,如何解決? 雖然也回答出來了,但是不夠全面體系化,
所以,小北給大家做一下系統化、體系化的梳理,幫助大家在面試過程中能夠脫穎而出,拿到自己心儀的Offer
插播一條:如果你近期準備面試跳槽,建議在http://cxykk.com線上刷題,涵蓋 1萬+ 道 Java 面試題,幾乎覆蓋了所有主流技術面試題。
1. 什麼是MySQL死鎖?
MySQL中的死鎖是指兩個或多個操作相互等待對方釋放資源,結果導致他們都無法繼續執行的情況。
可以想象成兩個人各自拿著對方需要的東西,卻都僵持不下,誰也不願意先放手。
在資料庫操作中,這通常發生在多個事務同時試圖鎖定對方已鎖定的資源時。
2. MySQL鎖的分類
MySQL的鎖可以從操作的粒度進行分類,主要包括表級鎖、行級鎖和頁級鎖。
不同類型的鎖在資料庫操作中的應用會影響資料庫的性能和併發處理能力。
表級鎖:
表級鎖是最簡單的鎖類型,當操作涉及到整個表時使用。
這種鎖會鎖定整個表,使得任何其他需要訪問這個表的操作都必須等待鎖被釋放。
例如:
--手動增加表鎖
lock table 表名稱 read(write),表名稱2 read(write);
--查看表上加過的鎖
show open tables;
--刪除表鎖
unlock tables;
優點是簡單易管理,但缺點是併發能力較低,尤其在處理大量事務時,效率會大大降低。
行級鎖:
行級鎖是最精細的鎖,只鎖定數據表中的特定行。
行級鎖的特點:
每次操作鎖住一行數據。開銷大,加鎖慢; 會出現死鎖; 鎖定粒度最小,發生鎖衝突的概率最低,併發度最高。
InnoDB相對於MYISAM的最大不同有兩點:
InnoDB支持事務(TRANSACTION) InnoDB支持行級鎖
註意,InnoDB的行鎖實際上是針對索引加的鎖(在索引對應的索引項上做標記),不是針對整個行記錄加的鎖。並且該索引不能失效,否則會從行鎖升級為表鎖。(RR級別會升級為表鎖,RC級別不會升級為表鎖)
比如我們在RR級別執行如下sql:
--where條件里的name欄位無索引
select * from account where name = 'lilei' for update;
則其它Session對該表任意一行記錄做修改操作都會被阻塞住
頁級鎖:
頁級鎖介於表級鎖和行級鎖之間,不是MySQL預設使用的鎖類型。
它鎖定資料庫頁(即一組行),粒度比表級鎖細,但比行級鎖粗。頁
級鎖可以減少鎖的數量,從而降低鎖競爭,但可能會引起更多的鎖衝突,尤其是當多個事務頻繁修改相鄰的數據時。
插播一條:如果你近期準備面試跳槽,建議在http://cxykk.com線上刷題,涵蓋 1萬+ 道 Java 面試題,幾乎覆蓋了所有主流技術面試題。
3 從操作的類型進行的mysql鎖的分類
讀鎖(S鎖):
性能特點:
讀鎖也被稱為共用鎖,它允許一個事務去讀取一行數據,並防止其他事務對這行數據進行寫操作,直到讀鎖被釋放。
但是,多個事務可以同時持有對同一資源的讀鎖,這意味著多個用戶可以同時讀取數據,而不會相互影響。
例如:
select * from T where id=1 lock in share mode
適用場景:
適用於那些讀取操作遠多於寫入操作的場景。
因為讀鎖可以共用,它支持高併發的讀取操作,使得多個用戶可以同時查詢數據而不會阻塞彼此。
寫鎖(X鎖):
性能特點:
寫鎖又稱為排他鎖,當一個事務對數據進行修改時,它會加上寫鎖。這個鎖會阻止其他任何事務讀取或修改同一數據,直到寫鎖被釋放。
寫鎖保證了數據在修改期間的完整性和一致性。
例如:
select * from T where id=1 for update
適用場景:
適用於需要修改數據的操作。
由於寫鎖會阻塞其他所有試圖訪問相同數據的操作,所以在寫入量大或者數據頻繁更新的應用中,寫鎖可能會成為性能瓶頸。
意向鎖:
性能特點:
意向鎖是一種較為特殊的鎖,它不直接鎖定數據,而是表明一個事務意圖對數據行進行加鎖(讀鎖或寫鎖)。
意向鎖主要分為:
意向共用鎖,IS鎖,對整個表加共用鎖之前,需要先獲取到意向共用鎖。 意向排他鎖,IX鎖,對整個表加排他鎖之前,需要先獲取到意向排他鎖。
這主要用於支持多級鎖定協議,通過在表級別設置意向鎖,來預告即將在行級別上加的鎖,這樣就能在不同粒度的鎖之間提供一種相容性檢查。
適用場景:
意向鎖主要用於提高併發性能,特別是在存在多粒度鎖定(即同時使用表級鎖和行級鎖)的情況下。
它允許資料庫系統更有效地管理鎖,避免不必要的鎖衝突,提高操作效率。
4 從操作的性能進行的mysql鎖的分類
從操作的性能可分為樂觀鎖和悲觀鎖
樂觀鎖:
性能特點:
樂觀鎖基於這樣一個假設,即衝突發生的概率較低,大多數時間不會有衝突。
因此,它在操作過程中不會立即鎖定資源。通常,樂觀鎖會通過檢查數據在讀取和更新期間是否被修改來實現,常用的方法是使用版本號或時間戳。只有在數據提交更新時,才會檢查版本信息是否一致,如果不一致,表示數據在此期間已被其他操作更改,此時操作會失敗。
適用場景:
適用於讀多寫少的場景,比如線上閱讀平臺的用戶數據處理,因為在這種場景中,數據衝突的可能性較低,使用樂觀鎖可以減少鎖的開銷,提高系統的整體性能。
悲觀鎖:
性能特點:
悲觀鎖恰恰相反,它假設衝突很常見,因此在整個數據處理過程中會保持數據鎖定,直到事務完成。
這意味著當一個事務在操作數據時,其他事務必須等待直到鎖被釋放。悲觀鎖可以通過資料庫自帶的鎖機制實現,比如行鎖或表鎖。
適用場景:
適合寫操作多的場景,比如銀行賬戶處理,在這種場景下,數據安全和一致性比性能更為重要。悲觀鎖通過鎖定數據來避免數據在多個事務間的衝突,確保數據操作的安全性。
5 InnoDB存儲引擎三種行鎖模式
當我們談論InnoDB存儲引擎中的行鎖模式時,可以把它想象成一種確保資料庫中數據安全和準確的機制。這裡有三種主要的行鎖模式,分別是記錄鎖、間隙鎖和臨鍵鎖。
5.1、記錄鎖(Record Locks):
記錄鎖是最直接的一種鎖。它就像是給資料庫中某條具體數據上了一把鎖。