臺上三分鐘,臺下三小時,兄弟們,今天咱們花三分鐘了解下資料庫中的兩種讀(select)操作:一致性非鎖定讀 和 一致性鎖定讀
一致性非鎖定讀
一致性非鎖定讀是什么?這里我先給出一個最最最簡單的解釋:一致性非鎖定讀就是讀快照!
快照即當前行資料之前的歷史版本,每行記錄可能存在多個歷史版本,或者說每行記錄可能有不止一個快照資料,一般我們將這種技術稱為 行多版本技術,而由于一個行記錄可能對應著多個快照(歷史版本),為此不可避免地會帶來一系列的并發問題,如何解決這些并發問題,就是所謂的 多版本并發控制(MVCC),當然,這不是本文的重點,
在不同事務隔離級別下,讀取的方式不同,只有在事務隔離級別 READ COMMITTED 和 REPEATABLE READ(默認)下,InnoDB 存盤引擎才會使用非鎖定的一致性讀,并且,即使都是使用非鎖定的一致性讀,它倆對于快照資料的定義也各不相同:
-
在 READ COMMITTED 事務隔離級別下,總是讀取行的最新版本;如果行被鎖定了,非一致性讀不會因此去等待行上鎖的釋放,而是去讀取該行版本的最新一個快照,如下圖所示:

-
在 REPEATABLE READ 事務隔離級別下,對于快照資料,非一致性讀總是讀取事務開始時的行資料版本
這么說可能還不是很好理解,舉個例子,這個時候又得掏出我們經典的 user 表了(滑稽),表中包含三個欄位 id、username、age,已存在一行記錄:
id = 1, username = 'Jack', age = 20;
1)第一步,我們開啟一個事務,執行如下陳述句:
事務 1:
begin;
select * from user where id = 1;
2)可以看到,第一個事務并沒有提交,這時,我們開啟第二個事務模擬并發,執行如下陳述句:
事務 2:
begin;
update user set id = 100 where id = 1;
3)在第二個事務中,將表中 id 為 1 的記錄修改為了 id=100,但是事務同樣沒有提交(即此時 id = 1 的行記錄被事務 2 加上了行鎖),這時如果在第一個事務中再次讀取 id 為 1 的記錄,那顯然還是 1 對吧:
事務 1:
select * from user where id = 1;

4)接著,我們再來提交下第 2 個事務中所作的修改:
事務 2:
commit;
由于當前 id = 1 的資料被修改成了 100,也就是說,當前 id = 100 的行記錄擁有了一個 id = 1 的歷史版本,

5)這個時候,再去事務 1 中讀取 id 為 1 的記錄,在 READ COMMITTED 和 REPEATABLE 事務隔離級別下得到結果就不一樣了:
-
對于 READ COMMITTED 的事務隔離級別,由于事務 2 已經提交了,也就是說 id = 1 的行記錄沒有被事務 2 鎖定,所以就會去讀取該行的最新版本,即 id = 100,So, 在 READ COMMITTED 的事務隔離級別下,此時查詢 id = 1 的結果是 Empty Set;
-
而在 REPEATABLE READ 事務隔離級別下,非一致性讀總是讀取事務開始時的行資料版本,也就是說,在事務 1 剛開始的時候,id = 1 的資料行是什么樣,現在讀到的就是什么樣的:

可以結合下面這張圖來回顧下上述的程序:

一致性鎖定讀
其實從名字上也能看出來,非一致性鎖定讀適用于對資料一致性要求不是很高的情況,比如在 READ COMMITTED 隔離級別下,即使行被鎖定了,非一致性讀也可以讀到該行版本的最新一個快照,也即,非鎖定讀機制極大地提高了資料庫的并發性,
而一致性鎖定讀適用于對資料一致性要求比較高的情況,這個時候我們需要對讀操作進行加鎖以保證資料邏輯的一致性,
InnoDB 存盤引擎對讀操作支持兩種一致性鎖定讀方式,或者說對讀操作支持兩種加鎖方式:
SELECT ... FOR UPDATE,對于讀取的行記錄加一個 X 排它鎖,其他事務不能對鎖定的行加任何鎖SELECT ... LOCK IN SHARE MODE,對于讀取的行記錄添加一個 S 共享鎖,其它事務可以向被鎖定的行加 S 鎖,但是不允許添加 X 鎖,否則會被阻塞住
So,如何用大白話解釋一致性鎖定讀?上面這兩條特殊的 select 陳述句就是一致性鎖定讀!一致性鎖定讀就是給行記錄加 X 鎖或 S 鎖!
簡單不?
?? 關注公眾號 | 飛天小牛肉,即時獲取更新
-
博主東南大學碩士在讀,攜程 Java 后臺開發暑期實習生,利用課余時間運營一個公眾號『 飛天小牛肉 』,2020/12/29 日開通,專注分享計算機基礎(資料結構 + 演算法 + 計算機網路 + 資料庫 + 作業系統 + Linux)、Java 技術堆疊等相關原創技術好文,本公眾號的目的就是讓大家可以快速掌握重點知識,有的放矢,關注公眾號第一時間獲取文章更新,成長的路上我們一起進步
-
并推薦個人維護的開源教程類專案: CS-Wiki(Gitee 推薦專案,現已累計 1.8k+ star), 致力打造完善的后端知識體系,在技術的路上少走彎路,歡迎各位小伙伴前來交流學習 ~ ??
-
如果各位小伙伴春招秋招沒有拿得出手的專案的話,可以參考我寫的一個專案「開源社區系統 Echo」Gitee 官方推薦專案,目前已累計 900+ star,基于 SpringBoot + MyBatis + MySQL + Redis + Kafka + Elasticsearch + Spring Security + ... 并提供詳細的開發檔案和配套教程,公眾號后臺回復 Echo 可以獲取配套教程,目前尚在更新中,
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/300938.html
標籤:MySQL
下一篇:Redis集群的安裝
