當前讀和快照讀

2021-09-24 21:22:57 字數 1514 閱讀 3517

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

innodb的預設事務隔離級別是rr(可重複讀)。它的實現技術是mvcc。基於版本的控制協議。該技術不僅可以保證innodb的可重複讀,而且可以防止幻讀。(這也就是是此前以rr隔離級別實踐時,不僅可以防止可重複讀,也防止了幻讀),但是它防止的是快照讀,也就是讀取的資料雖然是一致的,但是資料是歷史資料。

如何做到保證資料是一致的(可重複、幻)(也就是乙個事務,其內部讀取對應某乙個資料的時候,資料都是一樣的),同時讀取的資料是最新的資料。innodb提供了乙個間隙鎖的技術,即next-key,也就是結合grap鎖與行鎖,達到最終目的。當使用索引進行插入(或select,update等)的時候,innodb會將當前的節點(record_lock)和上乙個節點(gap lock)加鎖?。這樣當進行select的時候,就不允許加x鎖。那麼在進行該事務的時候,讀取的就是最新的資料。(同樣的,反過來看,當select in share mode時加next-key鎖,視查詢索引是否唯一而定一片資料的insert和update阻塞),當兩個當前讀在乙個事務中,別的update insert delete就無法打斷,也就不會出現重複讀和幻讀。

在乙個支援mvcc併發控制的系統中,哪些讀操作是快照讀?哪些操作又是當前讀呢?以mysql innodb為例:

快照讀:簡單的select操作,屬於快照讀,不加鎖。(當然,也有例外,下面會分析)

select * from table where ?;

簡單的select操作(不包括 select … lock in share mode, select … for update)

當前讀:特殊的讀操作,插入/更新/刪除操作,屬於當前讀,需要加鎖。

select * from table where ? lock in share mode;

select * from table where ? for update;

insert into table values (…);

update table set ? where ?;

delete from table where ?;

首先看看什麼是幻讀

幻讀。解決了不重複讀,保證了同乙個事務裡,查詢的結果都是事務開始時的狀態(一致性)。但是,如果另乙個事務同時提交了新資料,本事務再更新時,就會「驚奇的」發現了這些新資料,貌似之前讀到的資料是「鬼影」一樣的幻覺。

在mysql中,提供了兩種事務隔離技術,第乙個是mvcc,第二個是next-key技術。這個在使用不同的語句的時候可以動態選擇。不加lock inshare mode之類的快照讀就使用mvcc。否則 當前讀使用next-key。mvcc的優勢是不加鎖,併發性高。缺點是不是實時資料。next-key的優勢是獲取實時資料,但是需要加鎖。

因為預設的查詢語句是快照讀,而要避免幻讀需要使用當前讀。可以通過使用當前讀來規避幻讀問題。

當前讀和快照讀

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

mysql 快照讀和當前讀

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

Mysql快照讀和當前讀

讀取的是記錄資料的可見版本 可能是過期的資料 不用加鎖 讀取的是記錄資料的最新版本,並且當前讀返回的記錄都會加上鎖,保證其他事務不會再併發的修改這條記錄 概念說的比較虛,也不好理解,接著舉乙個例子吧,假設你開啟了兩個事務,分別是a和b,這裡有個張表,user表,裡面有四條資料 x表示是排它鎖 exc...