mysql mvcc 隔离级别_关于 Mysql 四种隔离级别中 Lock 和 MVCC 的关系
讀寫鎖
共享鎖(share lock)| 讀鎖(read lock)
讀鎖是共享的,或者說是相互不阻塞的。多個客戶在同一時刻可以同時讀取同一個資源,而互不干擾
SELECT ... LOCK IN SHARE MODE
排他鎖(exclusive lock)| 寫鎖(write locl)
寫鎖則是具有排他性,也就是說一個寫鎖會阻塞其他的寫鎖和讀鎖,只有這樣,才能確保在給定的時間里,只有一個用戶能執行寫入,并防止其他用戶讀取正在寫入的同一資源
SELECT ... FOR UPDATE
鎖粒度
表鎖(table lock)
對整張表進行控制
行級鎖(row lock)
對一行數據進行控制
多版本并發控制(MVVC)
大多數事物行存儲引擎實現的都不是簡單的行級鎖。基于提神并發性能的考慮,它們一般都同時實現了多版本并發控制。
MVCC 的實現,是通過保存數據在某一時間點的快照來實現。也就是說,不管需要執行多長時間,每個事物看到的數據都是一致的。根據事物開始的時間不同,每個事物對同一張表,同時刻看到的數據可能是不一致的。
Msql InnoDB 的 MVCC,是通過在每行記錄后面保存兩個隱藏的列來實現。這兩個列,一個保存列行的創建時間,一個保存行的過期時間(刪除時間)。當然存儲的并不是實際的時間值,而是系統版本號。每開始一個新的事物,系統版本號都會自動遞增。事物開始時刻的系統版本號會作為事物的版本號,用來查詢到每行記錄的版本號進行比較。
SELECT
InnoDB 會根據以下兩個條件檢查每行記錄:
InnoDB 只查找版本早于當前事物版本的數據行(也就是,行的系統版本號小于或等于事物的系統版本號),這樣可以確保事物讀取的行,要么是在事物開始前已存在的,要么是事物自身插入或者修改過的。
行的刪除版本要么未定義,要么大于當前事物版本號。這可以確保事物讀取到的行,在事物開始之前未被刪除。
只有符合上述兩個條件的記錄,才能返回作為查詢結果
INSERT
InnoDB 為新插入的每一行保存當前系統版本號作為行版本號
DELETE
InnoDB 為刪除的每一行保存當前系統版本號作為行刪除標識
UPDATE
InnoDB 為插入一行新記錄,保存當前系統版本號作為行版本號,同時保存當前系統版本號到原來的行作為行刪除標識
總結
保存這兩個額外系統版本號,使大多數讀操作都可以不用加鎖。這樣設計使得讀數據操作很簡單,性能很好,并且也能夠保證只會讀取到符合標準的行,不足之處是每行都要額外的儲存空間,需要做更多的行檢查工作,以及額外的維護工作。
MVCC 只在 REPEATABLE READ 和 READ COMMITTED 兩個隔離級別下工作。其他兩個隔離級別都和 MVCC 不兼容,因為 READ UNCOMMITTED 總是讀取最新的數據行,而不是符合當前事物版本的數據行。而 SERIALIZABLE 則會對所有讀取的行都加鎖
隔離級別
READ UNCOMMITTED(未提交讀)
事物可以讀取未提交的數據(臟讀)
READ COMMITTED(提交讀)
只能看見已經提交的事物所做的修改(不可重復讀)
REPEATABLE READ(可重復度)(默認隔離級別)
當前事物在讀取某個范圍內的記錄時,另外一個事物又在該范圍內插入了新的記錄,當前事物再次查詢時,會產生幻行(幻讀)
SERIALIZABLE(可串行化)
在讀取的每一行數據上都加鎖(排他鎖)
隔離級別
臟讀
不可重復讀
幻讀
加鎖讀
READ UNCOMMITTED
YES
YES
YES
NO
READ COMMITTED
NO
YES
YES
NO
REPEATABLE READ
NO
NO
YES
NO
SERIALIZABLE
NO
NO
NO
YES
PS:
樂觀鎖
樂觀鎖大多是基于數據版本記錄機制實現,一般是給數據庫表增加一個"version"字段。讀取數據時,將此版本號一同讀出,之后更新時,對此版本號加一。此時將提交數據的版本數據與數據庫表對應記錄的當前版本信息進行比對,如果提交的數據版本號大于數據庫表當前版本號,則予以更新,否則認為是過期數據。
悲觀鎖
悲觀鎖依靠數據庫提供的鎖機制實現。MySQL 中的共享鎖和排它鎖都是悲觀鎖。數據庫的增刪改操作默認都會加排他鎖,而查詢不會加任何鎖。
補充
當前讀、快照讀,record lock(記錄鎖)、gap lock(間隙鎖)、next-key lock
本來只有 SERIALIZABLE 隔離級別才可以解決幻讀問題,而實際上由于快照讀的特性使可重復讀也解決了幻讀問題。
當前讀是因為 innodb 默認為它加入了間隙鎖,防止在事務期間對相關數據集插入記錄,從而避免出現幻讀。
在 RR 級別下,快照讀是通過 MVVC(多版本控制)和 undo log 來實現的,當前讀是通過加 record lock(記錄鎖)和 gap lock(間隙鎖)來實現的。如果需要實時顯示數據,還是需要通過手動加鎖來實現。這個時候會使用 next-key 技術來實現。
在 MySQL 中,提供了兩種事務隔離技術,第一個是 mvcc,第二個是 next-key 技術。這個在使用不同的語句的時候可以動態選擇。不加 lock inshare mode 之類的快照讀就使用 mvcc。否則 當前讀使用 next-key。mvcc 的優勢是不加鎖,并發性高。缺點是不是實時數據。next-key 的優勢是獲取實時數據,但是需要加鎖。
Record lock
單條索引記錄上加鎖,record lock 鎖住的永遠是索引,而非記錄本身,即使該表上沒有任何索引,那么 innodb 會在后臺創建一個隱藏的聚集主鍵索引,那么鎖住的就是這個隱藏的聚集主鍵索引。所以說當一條 SQL 沒有走任何索引時,那么將會在每一條聚集索引后面加 X 鎖,這個類似于表鎖,但原理上和表鎖應該是完全不同的。
Gap Lock
在索引記錄之間的間隙中加鎖,或者是在某一條索引記錄之前或者之后加鎖,并不包括該索引記錄本身。gap lock 的機制主要是解決可重復讀模式下的幻讀問題。
Next-Key Lock
行鎖和間隙鎖組合起來就叫 Next-Key Lock。
總結
以上是生活随笔為你收集整理的mysql mvcc 隔离级别_关于 Mysql 四种隔离级别中 Lock 和 MVCC 的关系的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 倍福BECKHOFF PLC:自动化编程
- 下一篇: css 宋体_Java前端基础(一)之h