資料庫基礎知識詳解二:樂觀/悲觀鎖、封鎖級別、三級封鎖協議以及兩段鎖協議

投三分的金閃閃發表於2022-04-07

寫在文章前:本系列文章用於博主自己歸納複習一些基礎知識,同時也分享給可能需要的人,因為水平有限,肯定存在諸多不足以及技術性錯誤,請大佬們及時指正。

4.樂觀鎖和悲觀鎖

樂觀鎖和悲觀鎖在資料庫和多執行緒併發中常被提及,但它們並不是某兩個特定的鎖,而是兩個鎖的巨集觀理念。

  • 悲觀鎖:認為資料隨時會被修改,因此每次讀取資料之前都會上鎖,防止其它事務讀取或修改資料。應用於資料更新比較頻繁的場景。

  • 樂觀鎖:運算元據時不會上鎖,但是更新時會判斷在此期間有沒有別的事務更新這個資料,若被更新過,則失敗重試。適用於讀多寫少的場景。

樂觀鎖的實現方式有:
(1)加一個版本號或者時間戳欄位,每次資料更新時同時更新這個欄位。
(2)先讀取想要更新的欄位或者所有欄位,更新的時候比較一下,只有欄位沒有變化才進行更新。

5.常見的封鎖級別

意向鎖是 InnoDB (MySQL加的資料引擎)自動加的, 不需要使用者干預。 對於UPDATE、DELETE和INSERT 語句, InnoDB 會自動給涉及資料集加排他鎖(X)。對於普通SELECT 語句,InnoDB 不會加任何鎖。事務可以通過以下語句顯式給記錄集加共享鎖或排他鎖: 共享鎖(S):SELECT * FROM table_name WHERE ... LOCK IN SHARE MODE。 其他 session 仍然可以查詢記錄,並也可以對該記錄加 share mode 的共享鎖。但是如果當前事務需要對該記錄進行更新操作,則很有可能造成死鎖。 排他鎖(X):SELECT * FROM table_name WHERE ... FOR UPDATE。其他 session 可以查詢該記錄,但是不能對該記錄加共享鎖或排他鎖,而是等待獲得鎖。

排它鎖(Exclusive Lock)/ X鎖:事務對資料加上X鎖時,只允許此事務讀取和修改此資料,並且其它事務不能對該資料加任何鎖。

共享鎖(Shared Lock)/ S鎖:加了S鎖後,該事務只能對資料進行讀取而不能修改,並且其它事務只能加S鎖,不能加X鎖。

意向鎖(Intention Locks):一個事務在獲得某個資料行物件的 S 鎖之前,必須先獲得整個表的 IS 鎖或更強的鎖。一個事務在獲得某個資料行物件的 X 鎖之前,必須先獲得整個表的 IX 鎖。IS/IX 鎖之間都是相容的。

好處:如果一個事務想要對整個表加X鎖,就需要先檢測是否有其它事務對該表或者該表中的某一行加了鎖,這種檢測非常耗時。有了意向鎖之後,只需要檢測整個表是否存在IX/IS/X/S鎖就行了鎖的作用:用於管理對共享資源的併發訪問,保證資料庫的完整性和一致性。

封鎖粒度

MySQL 中提供了兩種封鎖粒度:行級鎖以及表級鎖

簡單來說即鎖住整張表或者鎖住一行的資料。

封鎖粒度小 封鎖粒度大
優點 鎖定的資料量較少,發生鎖競爭的可能較小,系統的併發性更好。 系統開銷較小。(加鎖、釋放鎖、檢查鎖的狀態都需要消耗資源)。
缺點 系統開銷較大大。 鎖定的資料量較多,發生鎖競爭的可能較大,系統的併發性較差。

6.三級封鎖協議

  • 一級封鎖協議:事務在修改資料之前必須先對其加X鎖,直到事務結束才釋放。

    可以解決丟失修改問題(兩個事務不能同時對一個資料加X鎖,避免了修改被覆蓋)

  • 二級封鎖協議:在一級的基礎上,事務在讀取資料之前必須先加S鎖,讀完後釋放。

    可以解決髒讀問題(如果已經有事務在修改資料,就意味著已經加了X鎖,此時想要讀取資料的事務並不能加S鎖,也就無法進行讀取,避免了讀取髒資料)

  • 三級封鎖協議:在二級的基礎上,事務在讀取資料之前必須先加S鎖,直到事務結束才能釋放。

    可以解決不可重複讀問題(避免了在事務結束前其它事務對資料加X鎖進行修改,保證了事務期間資料不會被其它事務更新)。

7.兩段鎖協議

什麼是兩段鎖協議?

定義:事務必須嚴格分為兩個階段對資料進行加鎖和解鎖的操作,第一階段加鎖,第二階段解鎖。

也就是說一個事務中一旦釋放了鎖,就不能再申請新鎖了。

可序列化排程是指,通過併發控制,使得併發執行的事務結果與某個序列執行的事務結果相同。

事務遵循兩段鎖協議是保證可序列化排程的充分條件(注意不是充要條件,而是充分條件。即事務遵循兩段鎖協議一定能保證可序列化排程,但保證可序列化排程不一定需要遵循兩段鎖協議)。

相關文章