加鎖是爲了保證數據的一致性程序員
1、按照鎖粒度進行劃分
缺點 | 優勢 | ||
表鎖 | 數據表進行鎖定 |
|
|
頁鎖 | 數據頁的粒度上進行鎖定 |
|
|
行鎖 | 行的粒度對數據進行鎖定 |
|
|
- 每一個層級的鎖數量是有限制的,鎖會佔用內存空間,鎖空間的大小是有限的
- 當某個層級的鎖數量超過了這個層級的閾值時,就會進行鎖升級
- 鎖升級就是用更大粒度的鎖替代多個更小粒度的鎖
- 好比 InnoDB 中行鎖升級爲表鎖,這樣作的好處是佔用的鎖空間下降了,但同時數據的併發度也降低
2、數據庫管理的角度對鎖進行劃分
共享鎖 |
|
|
排它鎖 |
|
|
意向鎖 |
|
|
3、共享鎖會發生死鎖
- 當有多個事務對同一數據得到讀鎖的時候,可能會出現死鎖的狀況
- 相互等待相互不釋放手上資源
4、程序員的角度對進行劃分
樂觀鎖 |
|
悲觀鎖 |
|
- 樂觀鎖適合讀操做多的場景,相對來講寫的操做比較少。它的優勢在於程序實現,不存在死鎖問題,不過適用場景也會相對樂觀,由於它阻止不了除了程序之外的數據庫操做
- 悲觀鎖適合寫操做多的場景,由於寫的操做具備排它性。採用悲觀鎖的方式,能夠在數據庫層面阻止其餘事務對該數據的操做權限,防止讀 - 寫和寫 - 寫的衝突。
5、MVCC
全稱是 Multiversion Concurrency Control,中文翻譯過來就是多版本併發控制技術。從名字中也能看出來,MVCC 是經過數據行的多個版本管理來實現數據庫的併發控制,簡單來講它的思想就是保存數據的歷史版本。這樣咱們就能夠經過比較版本號決定數據是否顯示出來(具體的規則後面會介紹到),讀取數據的時候不須要加鎖也能夠保證事務的隔離效果數據庫
快照讀讀取的是快照數據,不加鎖的簡單的 SELECT 都屬於快照讀併發
- 讀寫之間阻塞的問題,經過 MVCC 可讓讀寫互相不阻塞,即讀不阻塞寫,寫不阻塞讀,提高事務併發處理能力
- 下降了死鎖的機率。MVCC 採用了樂觀鎖的方式,讀取數據時並不須要加鎖,對於寫操做,也只鎖定必要的行
- 解決一致性讀的問題。一致性讀也被稱爲快照讀,當查詢數據庫在某個時間點的快照時,只能看到這個時間點以前事務提交更新的結果,而不能看到這個時間點以後事務提交的更新結果
InnoDB 中的 MVCC 實現
InnoDB 是如何存儲記錄的多個版本的。多版本對應 MVCC 前兩個字母的釋義:Multi Versionspa
事務版本號 |
|
||||||||||
行記錄的隱藏列 |
|
|
|||||||||
Undo Log |
|
|
Read View 如何工做
- 多個事務對同一個行記錄進行更新會產生多個歷史快照
- 歷史快照保存在 Undo Log 裏
- 若是一個事務想要查詢這個行記錄,須要讀取哪一個版本的行記錄?
- 須要用到 Read View 它幫咱們解決了行的可見性問題
- Read View 保存了當前事務開啓時全部活躍(尚未提交)的事務列表
- 換個角度你能夠理解爲 Read View 保存了不該該讓這個事務看到的其餘的事務 ID 列表
trx_ids | 系統當前正在活躍的事務 ID 集合 |
low_limit_id | 活躍的事務中最大的事務 ID |
up_limit_id | 活躍的事務中最小的事務 ID |
creator_trx_id | 建立這個 Read View 的事務 ID |
trx_ids 爲 trx二、trx三、trx5 和 trx8 的集合,活躍的最大事務 ID(low_limit_id)爲 trx8,活躍的最小事務 ID(up_limit_id)爲 trx2翻譯
- 當前有事務 creator_trx_id 想要讀取某個行記錄,這個行記錄的事務 ID 爲 trx_id,那麼會出現如下幾種狀況
- 若是 trx_id < 活躍的最小事務 ID(up_limit_id),也就是說這個行記錄在這些活躍的事務建立以前就已經提交了,那麼這個行記錄對該事務是可見的
- 若是 trx_id > 活躍的最大事務 ID(low_limit_id),這說明該行記錄在這些活躍的事務建立以後才建立,那麼這個行記錄對當前事務不可見
- 若是 up_limit_id < trx_id < low_limit_id,說明該行記錄所在的事務 trx_id 在目前 creator_trx_id 這個事務建立的時候,可能還處於活躍的狀態
- 所以須要在 trx_ids 集合中進行遍歷,若是 trx_id 存在於 trx_ids 集合中,證實這個事務 trx_id 還處於活躍狀態,不可見
- 不然,若是 trx_id 不存在於 trx_ids 集合中,證實事務 trx_id 已經提交了,該行記錄可見
當查詢一條記錄的時候,系統如何經過多版本併發控制技術找到它指針
- 首先獲取事務本身的版本號,也就是事務 ID
- 獲取 Read View
- 查詢獲得的數據,而後與 Read View 中的事務版本號進行比較
- 若是不符合 ReadView 規則,就須要從 Undo Log 中獲取歷史快照
- 最後返回符合規則的數據
- InnoDB 中,MVCC 是經過 Undo Log + Read View 進行數據讀取,Undo Log 保存了歷史快照,而 Read View 規則幫咱們判斷當前版本的數據是否可見
- 在隔離級別爲讀已提交(Read Commit)時,一個事務中的每一次 SELECT 查詢都會獲取一次 Read View
- 當隔離級別爲可重複讀的時候,就避免了不可重複讀,這是由於一個事務只在第一次 SELECT 的時候會獲取一次 Read View,然後面全部的 SELECT 都會複用這個 Read View
InnoDB 如何解決幻讀
記錄鎖 |
|
間隙鎖(Gap Locking) |
|
Next-Key 鎖 |
|