mysql MVCC 多版本併發控制

2021-10-02 03:13:08 字數 2327 閱讀 7272

mvcc是行級鎖的乙個變種,但是它在很多情況下避免了加鎖操作,因此開銷更低。大多數的mvcc都實現了非阻塞的讀操作,寫操作也只鎖定必要的行。主要是避免讀寫場景下加鎖控制的效能開銷。

multiversion concurrency control 多版本併發控制:併發訪問(讀或者寫)資料庫時,對正在事務內處理的資料做多版本的管理,用來避免由於寫操作的堵塞,而引發讀操作失敗的併發問題。

資料庫預設隔離級別:rr(repeatable read,可重複讀),mvcc主要適用於mysql的rc,rr隔離級別。序列化由於對行加鎖,也就不需要mvcc了。

可以認為mvcc是行級鎖的乙個變種,但是它在很多情況下避免了加鎖操作,因此開銷更低。大多數的mvcc都實現了非阻塞的讀操作,寫操作也只鎖定必要的行。解決了在repeatable read和read committed兩個隔離級別下讀同一行和寫同一行的兩個事務的併發。mvcc主要就是為了讓讀寫不衝突,提高效能。

mvcc的實現,是通過儲存資料在某個時間點的快照來實現的。也就是說,不管需要執行多長時間,每個事務看到的資料是一致的。根據事務開始的時間不同,每個事物對同一張表,同一時刻看到的資料可能是不一樣的。

背景:如果有多個寫操作,多個讀操作,可能兩次讀資料都不一樣,又可能後面一次讀取到寫入的資料,為了解決讀資料不一致的情況,有人提出了很多方法來解決這類問題,這類問題的解決方法叫做併發控制方法,mvcc也是其中乙個方法。

mvcc的思想就是:通過儲存資料在某個時間點的快照來實現的。這意味著乙個事務無論執行多長時間,在同乙個事務裡能夠看到資料一致的檢視,但這樣也會造成會一行記錄有多份。

主要實現就是我們看下,首先了解在mysql中建表時,每個表都會有三列隱藏記錄,其中和mvcc有關係的有兩列:

沒一行資料都會有這裡兩列,記錄版本號,我們來看下增刪改查的對版本號的影響: id

test_id

db_trx_id

db_roll_pt568

1null678

1null

begin;   --   獲取全域性系統事務id 假設為 10

update test_zq set test_id = 22 where id = 5;

commit;

更新id =5 的記錄:

idtest_id

db_trx_id

db_roll_pt568

110678

1null522

10null

begin;--獲得全域性事務id = 3

delete test_zq where id = 6;

commit;

id

test_id

db_trx_id

db_roll_pt568

1null678

13有點繞口,重點是注意到要有快照,我們會陷入這樣的邏輯黑洞裡:

(1)查詢資料的事務版本號是2,有乙個事務在update 資料,update 事務版本號是3,並且提交了事務。

(2)事務2開始讀資料,update 操作會有兩個記錄,老記錄滿足查詢條件,最後把老記錄給查詢出來了,也就是如下表的 id =5 的第一條記錄。

idtest_id

db_trx_id

db_roll_pt568

13678

1null522

3null

update 改為delete 似乎也是這樣的,但我自己理解,這裡有乙個誤解:

客觀上,mvcc就是樂觀鎖的一整實現方式,就是每行都有版本號,儲存時根據版本號決定是否成功。innodb中通過undo log實現了資料的多版本,而併發控制通過鎖來實現。有些理解可能是錯的,希望大家看到後可以及時反饋,讓我迷途知返。

innodb是在undolog中實現mvcc,通過undolog可以找回資料的歷史版本。找回的資料歷史版本可以提供給使用者讀(按照隔離級別的定義,有些讀請求只能看到比較老的資料版本),也可以在回滾的時候覆蓋資料頁上的資料。根據版本鏈來獲取歷史的資料。

我們直接給出幻讀定義:兩次讀的資料數量不一樣,其他事務insert或delete操作,導致兩次讀資料不一樣。查閱了一些資料後發現在rr級別中,通過mvcc機制,雖然讓資料變得可重複讀,但我們讀到的資料可能是歷史資料,不是資料庫最新的資料。這種讀取歷史資料的方式,我們叫它快照讀 (snapshot read),而讀取資料庫最新版本資料的方式,叫當前讀 (current read)。

所以在快照讀的情況下,是可以避免幻讀的,但在當前讀情況下無法避免幻讀。

舉個簡單的例子:

根據資料庫隔離級別,我們可以看到:

一文理解mysql mvcc

【mysql(5)| 五分鐘搞清楚 mvcc 機制】

mysql的可重複讀級別能解決幻讀嗎

MYSQL MVCC多版本併發控制

innodb使用mvcc實現高併發 mvcc並不是mysql獨有的,oracle,postgresql等都實現了mvcc,但各自實現機制不同。因為mvcc沒有統一實現標準。mvcc可以認為它是行級鎖的乙個變種,但是它在很多情況下避免了加鎖操作,因此開銷更低。實現了非阻塞的讀操作,寫操作也只鎖定必要的...

mysql mvcc多版本併發控制

事務隔離的實現方案有兩種,lbcc和mvcc 基於鎖的併發控制,英文全稱lock based concurrent control。這種方案比較簡單粗暴,就是乙個事務去讀取一條資料的時候,就上鎖,不允許其他事務來操作 當然這個鎖的實現也比較重要,如果我們只鎖定當前一條資料依然無法解決幻讀問題 這個概...

Mysql MVCC多版本併發控制原理詳解

我們建立乙個hero表 create table hero number int,name varchar 100 country varchar 100 primary key number engine innodb charset utf8 然後向這個表裡插入一條資料 insert into ...