MySQL --- 讀書筆記 --- 鎖
2. 併發事務訪問相同記錄的情況
2.1 讀-讀情況
讀取操作並不會對記錄有任何影響,所以允許這種情況的發生
2.2 寫-寫情況
對相同記錄做出改動,在這種情況下會出現髒寫
情況,任何一種隔離級別都不允許這種情況的發生,所以多個未提交事務對一條記錄做改動時,都需要排隊執行
,排隊的過程是通過鎖
實現的。
這個所謂鎖
是一個記憶體中的結構
,在事務執行之前本來是沒有鎖的,當一個事務想對記錄做改動時,首先看看記憶體有沒有與這條記錄相關聯的鎖結構
,當沒有的時候,就會生成一個與之關聯的鎖
結構,這稱為獲取鎖成功
。
然後在這個事務提交之前,另一個事務也想對這條記錄改動時,也會想檢視與之關聯的鎖
結構,當發現有鎖時,也會生成一個鎖結構與之關聯,但是需要等待,這稱為獲取鎖失敗
當第一個事務結束後,就會把相應的鎖結構釋放,並檢視是否別的事務在等待,如果有,就會喚醒該事務
2.3 讀-寫或寫-讀情況
當一個事務讀取記錄,另一個事務改動記錄,這種情況下就會出現髒讀
、不可重複讀
和幻讀
問題
- 讀寫都加鎖
- 讀取記錄採用
MVCC
,改動記錄採用鎖
鎖的不同角度分類
3.1 從資料操作的型別劃分
對於InnoDB來說,讀鎖/寫鎖可以加在表上,也可以在行上
1. 讀鎖/共享鎖
英文S
表示,針對同一份資料,多個事務的讀操作同時進行,相互不阻塞
SELECT ... FOR SHARE;
2. 寫鎖/排他鎖
英文X
表示,在當前操作未完成前,阻斷其他寫鎖或讀鎖
SELECT ... FOR UPDATE;
3.2 從資料操作的粒度劃分
1. 表鎖
該鎖會鎖定這個張表的記錄,是MySQL中最基本的鎖策略,並不依賴於儲存引擎,它的開銷最小
,可以很好的避免死鎖
問題,但是隨之而來的鎖競爭發生的概率也會提高,導致併發率大打折扣
- 表級別的S、X鎖
- 意向鎖
InnoDB支援多粒度鎖
,允許行級鎖與表級鎖共存
- 意向鎖是為了協調行鎖和表鎖的關係
- 意向鎖是一種
不與行級鎖衝突的表級鎖
- 表明“某個事務正在某些行持有鎖或該事務準備去持有鎖”
- 自增鎖
- 元資料鎖
意向鎖是由儲存引擎維護,使用者無法手動操作,在為資料行加S/X鎖時,會先獲取該資料行所在資料表的意向鎖
意向鎖解決的問題:假設有兩個事務t1和t2,當t2想要給表加上S/X鎖,那麼它需要檢查表中每一行記錄是否存在鎖,但是如果我們有意向鎖,當t1給表中某些記錄加鎖時,首先給表新增意向鎖,然後當t2想要進行表級鎖時,就可以直接知道表中某些記錄被其他事務鎖定了
2. 行鎖
- 優點:粒度小,發生鎖衝突概率低,併發度高
- 缺點:開銷大,加鎖慢,容易出現死鎖
- 記錄鎖
- 間隙鎖
在解決幻讀問題上,當使用鎖
的方案時,事務讀取記錄時,幻影記錄還沒新增,我們無法給幻影記錄加上記錄鎖,這時就要用到間隙鎖
假設給一條記錄加上間隙鎖,那麼這條記錄的前邊就不允許插入記錄,或者說當主鍵3和主鍵8之間沒有其他記錄,當給主鍵8這條記錄加上間隙鎖,那麼不允許插入主鍵是3-8之間的記錄
無論是共享間隙鎖或者排他間隙鎖,並不限制其他事務對這條記錄加記錄鎖或者間隙鎖
- 臨鍵鎖
當既想鎖定某條記錄,又阻止其他事務在該記錄的前邊間隙插入新記錄,這時就用到臨鍵鎖,它只在InnoDB中的可重複讀的隔離級別下使用,InnoDB的預設鎖就是臨鍵鎖
本質是一個記錄鎖和間隙鎖的合體
- 插入意向鎖
InnoDB規定事務在等待的時候也需要在記憶體中生成一個鎖結構
當事務希望插入新記錄時,但是遇到間隙鎖需要等待時,生成一個插入意向鎖,它是一種Gap鎖
不是意向鎖
它是一種特殊的間隙鎖,當插入記錄之間不同時,互相不排斥