Mysql 共享鎖、排他鎖 與 事務隔離級別詳解

共享鎖、排他鎖

InnoDB 實現了兩種類型的鎖機制:共享鎖(S)和排他鎖(X)。共享鎖容許一個事務讀數據,不容許修改數據,若是其餘事務要再對該行加鎖,只能加共享鎖;排他鎖是修改數據時加的鎖,能夠讀取和修改數據,一旦一個事務對該行數據加鎖,其餘事務將不能再對該數據加任務鎖。數據庫

共享鎖(S) 排它鎖(X)
共享鎖(S) 容許 不容許
排它鎖(X) 不容許 不容許

x軸:事務A擁有的鎖
y軸:事務B申請的鎖微信

:一個事務在某一行數據上加上排它鎖後,其餘事務不能再在這行數據加任何鎖,沒法進行 update 與 delete,可是普通的 select 是能夠的,由於普通的 select 不加任何鎖,當 select .... from ... for update 時纔會加上排它鎖。併發

併發事務帶來的問題

1.數據丟失(兩個事務同時修改一行數據,其中一個事務異常回滾,致使更新失敗)spa

解決辦法:未提交讀(Read Uncommitted):在事務 B 讀取數據時,事務 A 讀取數據加了共享鎖,修改數據時加了排它鎖。這種隔離級別,會致使髒讀、不可重複讀以及幻讀。3d

微信截圖_20200413230833.png

未提交讀會致使髒讀、不可重複讀、幻讀的緣由:儘管 A 持有排它鎖,避免了兩個事務同時修改的狀況,可是普通的 select 不持有鎖,仍是能夠讀到數據的,因此事務 A 屢次修改數據,事務 B 中的查詢仍是能夠看到的。code

2.髒讀(一個事務的執行期間,另外一個事務讀到了沒有提交數據)blog

解決辦法:已提交讀(Read Committed):在事務 B 讀取數據時增長了共享鎖,一旦讀取,當即釋放鎖,事務 A 讀取修改數據時增長了行級排他鎖,直到事務結束才釋放鎖。
也就是說,事務 B 在讀取數據時,事務 A 只能讀取數據,不能修改。當事務 B 讀取到數據後,事務 A 才能修改。
這種隔離級別,能夠避免髒讀,但依然存在不可重複讀以及幻讀的問題。事務

微信截圖_20200413223229.png

已提交讀會致使不可重複讀、幻讀的緣由:事務 B 沒有提交就將鎖釋放,致使事務 A 能夠對數據進行任意修改,修改後,事務 B 再次獲取共享鎖查詢,查詢到跟以前讀取不一致的數據。rem

3.不可重複讀(一個事務的執行期間,另外一個事務連續兩次讀取到的值不同)it

解決辦法:可重複讀(Repeatable Read):在事務 B 讀取數據時增長了共享鎖,事務結束,才釋放鎖,事務 A 讀取修改數據時增長了行級排他鎖,直到事務結束才釋放鎖。
也就是說,事務 B 在沒有結束事務時,事務 A 只能讀取數據,不能修改。當事務 B 結束事務,事務 A 才能修改。
這種隔離級別,能夠避免髒讀、不可重複讀,但依然存在幻讀的問題。

微信截圖_20200413225430.png

可重複讀致使幻讀的緣由:可重複讀是加的行級鎖,而幻讀是知足查詢條件的前提下數據量發生變化,即發生 insert 或 delete操做。

4.幻讀(一個事務的執行期間,另外一個事務連續兩次讀取到的數量不一樣)

解決辦法:可序列化(Serializable):在事務 A 讀取數據時增長了共享鎖,事務結束,才釋放鎖,事務 B 讀取修改數據時增長了表級排他鎖,直到事務結束才釋放鎖。

可序列化解決了髒讀、不可重複讀、幻讀等問題,但隔離級別愈來愈高的同時,併發性會愈來愈低。

微信截圖_20200413230447.png

小結

能夠看出,控制數據庫併發帶來的問題依賴的是鎖粒度的擴大來解決的。

可是隔離級別越大,併發性就越差,若是業務場景容許的狀況下,適當減少隔離級別是處理併發的一種手段。

相關文章
相關標籤/搜索