MySQL的多版本併發控制MVCC的實現

2022-09-21 00:27:10 字數 1397 閱讀 7975

目錄

mvcc就是多版本併發控制。

mysql的事務型儲存引擎通過多版本併發控制(mvcc)來提公升併發效能。

可以認為mvcc是行級鎖的乙個變種,但是它在大多數情況下避程式設計客棧免了加鎖操作,同時實現非阻塞的讀操作,因此開銷更低。

mvcc是通過儲存資料在某個時間點的快照來實現的,核心思想就是儲存資料的歷史版本,通過對資料行的多個版本管理來實現資料庫的併發控制。

這樣我們就可以通過比較版本號決定資料是否顯示出來,讀取資料的時候不需要加鎖也可以保證事務的隔離效果。

實際上,innodb 會在每行記錄後面增加三個隱藏字段:

以 rr 級別為例:

每開啟乙個事務時,系統會給該事務分配乙個事務 id,在該事務執行第一 個 select 語句的時候,會生成乙個當前時間點的事務快照 readview,主要包含以下幾個屬性:

有了這個 readview,這樣在訪問某條記錄時,只需要按照下邊的步驟判斷記錄的某個版本是否可見:

在進行判斷時,首先會拿記錄的最新版本來比較,如果該版本無法被當前事務看到,則通過記錄的 roll_ptr 找到上乙個版本,重新進行比較,直到找到乙個能被當前事務看到的版本。

而對於刪除,其實就是一種特殊的更新,innodb 用乙個額外的標記位 delete_bit 標識是否刪除。當我們在進行判斷時,會檢查下 delete_bit 是否被標記,如果是,則跳過該版本,通過 roll_ptr 拿到下乙個版本進行判斷。

以上內容是對於 rr 級別來說,而對於 rc 級別,其實整個過程幾乎一樣,唯一不同的是生成 readview 的時機, rr 級別只在事務開始時生成一次,之後一直使用該 readview。而 rc 級別則在每次 select 時,都會生成乙個 readview。

幻讀:在乙個事務中使用相同的 sql 進行兩次讀取,第二次讀取到了其他事務新插入的行。

例如:1)事務 1 第一次查詢:select * from user where id < 10時查到了 id = 1 的資料

2)事務 2 插入了 id = 2 的資料

3)事務 1 使用同樣的語句第二次查詢時,查到了 id = 1、id = 2 的資料,出現了幻讀。

談到幻讀,首先我們要引入「當前讀」和「快照讀」的概念。

對於快照讀,mvcc 因為從 readview 讀取,所以必然不會看到新插入的行,所以天然就解決了幻讀的問題。

而對於當前讀的幻讀,mvcc 是無法解決的。需要使用 gap lock 或 next-key lock(gap lock + record lock)來解決。

其實原理也很簡單,用上面的例子稍微修改下以觸發當前讀:

select * from user where id < 10 for update

當使用了 gap lock 時,gap 鎖會鎖住 id < 10 的整個範圍,因此其他事務無法插入 id < 10 的資料,從而防止了幻讀。

Mysql多版本併發控制

mysql的絕大多數事務型儲存引擎都不是簡單的行級鎖。他們實現了多版本的併發控制,也就是mvvc,當然,支援mvvc的資料庫並不只有mysql,orcale postgresql等都實現了mvvc,只不過他們實現的方式不同而已,因為mvvc沒有乙個統一的規範。其實mvvc可以理解為行級鎖的一種變異,...

MySQL 架構 多版本併發控制

大部分的mysql的儲存引擎,比如innodb,falcon,以及pbxt並不是簡簡單單的使用行鎖機制。它們都使用了行鎖結合一種提高併發的技術,被稱為mvcc 多版本併發控制 mvcc並不單單應用在mysql中,其他的資料庫如oracle,postgresql,以及其他資料庫也使用這個技術。mvcc...

mysql多版本併發控制MVCC

innodb的mvcc是通過在每行記錄的後面儲存兩個隱藏的列來實現的,這兩個列乙個儲存行的建立時間,乙個儲存行的過期時間。但是並不是儲存時間而是儲存版本號,每開始乙個新的事務,版本號會自動遞增。事務開始時刻的系統版本號會作為事務的版本號,用來和查詢到每行記錄的版本號進行比較。select innod...