MySql學習(專項篇)MVCC

MVCC(Mutil-Version Concurrency Control)

MVCC是用於數據庫提供併發訪問控制的併發控制技術。與MVCC相對的,是基於鎖的並
發控制, Lock-Based Concurrency Control 。

MVCC的優點

MVCC最大的好處,相信也是耳熟能詳:讀不加鎖,讀寫不衝突

在讀多寫少的OLTP應用中,讀寫不衝突是非常重要的,極大的增加了系統的併發性能,這也是爲什麼現階段,幾乎所有的RDBMS,都支持了MVCC。
多版本併發控制僅僅是一種技術概念,並沒有統一的實現標準。
其核心理念就是數據快照,不同的事務 訪問不同版本的數據快照,從而實現不同的事務隔離級別。雖然字面上是說具有多個版本的數據快照,但這並不意味着數據庫必須拷貝數據,保存多份數據文件,這樣會浪費大量的存儲空間。
InnoDB通過事務的undo日誌巧妙地實現了多版本的數據快照。

MVCC中讀操作

在MVCC併發控制中,讀操作可以分成兩類:快照讀 (snapshot read)與當前讀 (current read)

  • 快照讀,讀取的是記錄的可見版本 (有可能是歷史版本),不用加鎖。
  • 當前讀,讀取的是記錄的最新版本,並且當前讀返回的記錄,都會加上鎖,保證其他事務不會再併發修 改這條記錄。

快照讀

在InnoDB中簡單的select操作屬於快照讀。

select * from table where ?;

當前讀

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

select * from table where ? lock in share mode;//共享鎖(S)
select * from table where ? for update;//排他鎖(X)
insert into table values () ; //排他鎖(X)
update table set ? where ? ; //排他鎖(X)
delete from table where ? ; //排他鎖(X)

所有以上的語句,都屬於當前讀,讀取記錄的最新版本。並且,讀取之後,還需要保證其他併發事務不
能修改當前記錄,對讀取記錄加鎖。
爲什麼將 插入/更新/刪除 操作,都歸爲當前讀?
首先我們要了解一下一個更新語句的執行流程

  1. 當Update SQL被髮給MySQL後,MySQL Server會根據where條件,讀取第一條滿足條件的記
    錄,然後InnoDB引擎會將第一條記錄返回,並加鎖 (current read)。
  2. 待MySQL Server收到這條加鎖的記錄之後,會再發起一個Update請求,更新這條記錄。
  3. 一條記錄操作完成,再讀取下一條記錄,直至沒有滿足條件的記錄爲止。

因此,Update操作內部,就包含了一個當前讀。同理,Delete操作也一樣。Insert操作會稍微有些不
同,簡單來說,就是Insert操作可能會觸發Unique Key的衝突檢查,也會進行一個當前讀。

一致性非鎖定讀

一致性非鎖定讀(consistent nonlocking read)是指InnoDB存儲引擎通過多版本控制(MVCC)讀取當前數
據庫中行數據的方式。如果讀取的行正在執行DELETE或UPDATE操作,這時讀取操作不會因此去等待行
上鎖的釋放。相反地,InnoDB會去讀取行的一個快照。
在這裏插入圖片描述
上圖直觀地展現了InnoDB一致性非鎖定讀的機制。之所以稱其爲非鎖定讀,是因爲不需要等待行上排
他鎖的釋放。快照數據是指該行的之前版本的數據,每行記錄可能有多個版本,一般稱這種技術爲行多
版本技術。由此帶來的併發控制,稱之爲多版本併發控制(Multi Version Concurrency Control,
MVCC)。InnoDB是通過undo log來實現MVCC。
在事務隔離級別READ COMMITTED和REPEATABLE READ下,InnoDB默認使用一致性非鎖定讀。然
而,對於快照數據的定義卻不同。在READ COMMITTED事務隔離級別下,一致性非鎖定讀總是讀取被
鎖定行的最新一份快照數據。而在REPEATABLE READ事務隔離級別下,則讀取事務開始時的行數據版
本。

InnoDB的MVCC實現

InnoDB使用undolog(版本鏈)和ReadView可見性判斷,去實現了MVCC。
在READ COMMITTD 、 REPEATABLE READ這兩個隔離級別通過生成 ReadView 的時機不同,

  1. READ COMMITTD 在每一次進行普通 SELECT 操作前都會生成一個 ReadView ,
  2. REPEATABLE READ 只在第一次進行普通 SELECT 操作前生成一個 ReadView ,之後的查詢操作都重複這個 ReadView
    就好了

從而實現讀不加鎖的情況下,讀寫不衝突,同時還能保證事務的隔離性程,這樣子可以使不同事務的 讀-寫 、 寫-讀 操作併發執行,從而提升系統性能。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章