當前讀和快照讀的區別

2021-10-10 13:57:33 字數 1926 閱讀 9627

本節內容就來聊聊這個話題,首先從快照讀開始:

1.1 定義

普通讀(也稱快照讀,英文名:consistent read),就是單純的 select 語句,不包括下面這兩類語句:

select ... for update 

select ... lock in share mode

普通讀的執行方式是生成 readview,直接利用 mvcc 機制來進行讀取,並不會對記錄進行加鎖。

小貼士對於 serializable 隔離級別來說,如果 autocommit 系統變數被設定為off,那普通讀的語句會轉變為鎖定讀,和在普通的 select 語句後邊加 lock in share mode 達成的效果一樣。

1.2 實現方式

普通讀是通過 undo log + mvcc 來實現的,具體我們再仔細聊聊:

下圖右側黃色部分是資料:一行資料記錄,主鍵 id 是 10,object = 'goland'  ,被 update 更新為 object = 'python' 。

事務會先使用「排他鎖」鎖定該行,將該行當前的值複製到 undo log 中,然後再真正地修改當前行的值,最後填寫事務的 db_trx_id ,使用回滾指標 db_roll_ptr 指向 undo log 中修改前的行。

這裡解釋一下 db_trx_id 和 db_roll_ptr 所代表的含義:

小貼士insert undo log 只在事務回滾時需要, 事務提交就可以刪掉了。update undo log 包括 update 和 delete , 回滾和快照讀都需要。

聊完快照讀,再聊聊當前讀(也稱鎖定讀,locking read)。

2.1 定義

當前讀,讀取的是最新版本,並且需要先獲取對應記錄的鎖,如以下這些 sql 型別:

select ... lock in share mode 、

select ... for update、

update 、delete 、insert

當然,獲取什麼型別的鎖取決於當前事務的隔離級別、語句的執行計畫、查詢條件等因素。例如,要 update 一條記錄,在事務執行過程中,如果不加鎖,那麼另乙個事務可以 delete 這條資料並且能成功 commit ,就會產生衝突了。所以 update 的時候肯定要是當前讀,得到最新的資訊並且鎖定相應的記錄。

2.2 實現方式

當前讀是通過 next-key 鎖(行記錄鎖+間隙鎖)來是實現的。

這裡補充下行鎖的 3 種演算法:行鎖(record lock):鎖直接加在索引記錄上面。

間隙鎖(gap lock):是 innodb 為了解決幻讀問題時引入的鎖機制,所以只有在 read repeatable 、serializable 隔離級別才有。

next-key lock :record lock + gap lock,鎖定乙個範圍並且鎖定記錄本身 。

下面通過乙個例子來說明當前讀的實現方式,例如下面這條 sql:

delete from t where age = 7;

進行下面的實驗:

測試可知 delete from t where age = 7; 語句在 age 上的加鎖區間為 (4,10) ,**如下:

當前讀和快照讀

在mvcc併發控制中,讀操作可以分成兩類 快照讀 snapshot read 與當前讀 current read 快照讀,讀取的是記錄的可見版本 有可能是歷史版本 不用加鎖。當前讀,讀取的是記錄的最新版本,並且,當前讀返回的記錄,都會加上鎖,保證其他事務不會再併發修改這條記錄。innodb的預設事務...

當前讀和快照讀

innodb的預設事務隔離級別是rr 可重複讀 它的實現技術是mvcc。基於版本的控制協議。該技術不僅可以保證innodb的可重複讀,而且可以防止幻讀。但是它防止的是快照讀,也就是讀取的資料雖然是一致的,但是資料是歷史資料。如何做到保證資料是一致的 也就是乙個事務,其內部讀取對應某乙個資料的時候,資...

mysql 快照讀和當前讀

以下都是在可重複讀隔離級別情況下的 快照讀 普通的不加鎖的select就是快照讀。通過readview實現,可重複讀級別時,整個事務的普通select都是使用同乙個readview。readview相關請看文章 總之,可以理解為當前事務建立後,會立即生成乙個快照,查詢的結果都是基於這個快照。新的其他...