MySQL MVCC 原理硬核解析,阿里面試官看了都直呼內行

張哥說技術發表於2023-11-09

來源:mikechen的網際網路架構

MVCC 是提高 MySQL 資料庫效能和併發效能的關鍵。

MVCC 是一種強大的資料庫併發控制機制,它可以解決併發訪問資料庫時的很多問題,例如死鎖、快照讀、讀寫阻塞等。

當出現讀寫衝突時,MVCC 在不加鎖、或儘量減少鎖使用的情況下,也能高效處理讀寫衝突,實現非阻塞併發讀。

MySQL MVCC 原理硬核解析,阿里面試官看了都直呼內行

大家好,我是 mikechen。

本文主要詳解 MVCC,MVCC 是資料庫效能最佳化提升的關鍵,也是大廠面試高頻,非常重要。為方便大家系統學習,我已將本文歸納到《MySQL面試題專項突擊》PDF,約 20 萬字,全部是大廠高頻必考,拉到文末可自取。

MySQL MVCC 原理硬核解析,阿里面試官看了都直呼內行


注:MyIsam 不支援事務,本文圍繞 InnoDB 引擎來講


01
   什麼是 MVCC

MVCC 又稱為多版本併發控制,英文全拼 Version Concurrency Control

MVCC 為每一個事務建立多個資料版本,每個版本對應一個特定時間點的資料庫狀態。

不同事務之間,彼此不干擾,基於各自的時間點,進行讀取和寫入操作。

想要更好掌握 MVCC ,有必要先了解當前讀快照讀。


02
   當前讀

當前讀Current Read)讀取的是最新資料,而不是歷史的資料。

加鎖的 SELECT、或對資料進行增刪改,都會進行當前讀

MySQL MVCC 原理硬核解析,阿里面試官看了都直呼內行

當前讀常用於需要讀取最新資料狀態的場景。

例如,庫存管理系統、實時監控系統等。

當前讀的特點:

  • 事務在讀取資料時,每次都會讀取當前的最新資料版本。


  • 事務在讀取資料時,不允許寫入;在寫入資料時,不允許其他事務讀取。


  • 當前讀允許讀取當前事務未提交的資料,在併發環境中,可能導致一致性問題。


03
   快照讀

快照讀(Snapshot Read,又稱為一致性讀 。

快照讀讀取的是快照資料,不加鎖的普通 SELECT ,都屬於快照讀。

MySQL MVCC 原理硬核解析,阿里面試官看了都直呼內行

快照讀用於需要事務隔離和資料一致性的場景。

例如,報表生成、資料分析和歷史查詢等。

快照讀的特點:

  • 在讀取資料時,會讀取建立事務時的資料版本,不受其他事務影響。


  • 由於它只讀取已提交的資料版本,確保了資料的一致性和隔離


  • 提供了事務開始時的資料一致性檢視,避免了併發衝突和未提交資料的影響。


快照讀和當前讀的區別:

  • 快照讀:僅讀取已提交的資料版本,不讀取其他事務未提交的資料。

  • 當前讀:讀取的是最新資料,而不是歷史的資料。


04   MVCC 的主要作用


MVCC 的作用是提高資料庫的併發效能。

  • 併發讀-寫時:讀操作不阻塞寫操作,寫操作也不會阻塞讀操作,避免了同一資料在不同事務之間的競爭。


  • 併發訪問資料庫時:解決了幻讀、不可重複讀等事務隔離問題。


MVCC 可以適應不同的應用需求,因為它允許讀未提交讀已提交可重複讀序列化不同的事務隔離級別。

MySQL MVCC 原理硬核解析,阿里面試官看了都直呼內行

由於資料庫不允許多個事務同時寫入相同的資料,故 髒寫 不會出現。

我們來看下,三種常見的 MySQL 資料庫併發場景:

  • 讀 - 讀:通常不會存在任何問題,也不需要併發控制。


  • 讀 - 寫:有執行緒安全問題,可能會造成髒讀,幻讀,不可重複讀,需要 MVCC 控制。


  • 寫 - 寫:有執行緒安全問題,可能會存在更新丟失問題,例如第一類更新丟失, 第二類更新丟失等。


對比下,

  • 沒有引入 MVCC 機制前

    僅 讀-讀 可以併發執行,讀-寫、寫-寫 都會阻塞,併發效能較差。


  • 引入 MVCC 機制後

    只有 寫-寫 之間相互阻塞,其他操作都可以並行,併發效能較高。


05
   MVCC 的實現原理

MVCC 機制的實現核心是隱藏列事務鏈 和 ReadView

隱藏鏈

Innodb 為每行記錄都新增了三個隱藏欄位:row_id、trx_id、roll_pointer。

以確保資料的一致性和事務管理。

MySQL MVCC 原理硬核解析,阿里面試官看了都直呼內行

事務鏈

每次對記錄進行 update 或者 delete 操作時,都會記錄一條 undo log 資訊。

每條 undo log 資訊中,都有一個 roll_pointer 屬性。

透過 roll_pointer ,將這些 undo 日誌串成一個連結串列,構成資料的事務鏈,如下圖所示

MySQL MVCC 原理硬核解析,阿里面試官看了都直呼內行

由於一個記錄會被一堆事務進行修改,在一個記錄中,就會存在多個版本的 Undo log 資訊。

那麼,這麼多個版本的Undo log 資訊,事務應該看到哪個

這裡就要了解 ReadView 機制。

ReadView

ReadView,又稱為讀檢視。

ReadView 是用於控制事務讀取資料的邏輯檢視,我們可以理解它為資料庫中某一個時刻所有未提交事務的快照。

透過 ReadView ,可以確定一個事務能夠看到哪些資料版本。

每個事務都會建立一個自己獨有的 ReadView,記錄當前活躍且未提交事務。

ReadView 的幾個重要引數:

MySQL MVCC 原理硬核解析,阿里面試官看了都直呼內行

當事務在進行快照讀時,會生成一個 ReadView 來進行可見性判斷,去判斷哪個版本的資料可讀

可見性判斷是由可見性演算法來確定的。

可見性演算法的規則:

MySQL MVCC 原理硬核解析,阿里面試官看了都直呼內行

不同隔離級別下,生成 ReadView 的邏輯:

序列化不需要版本鏈,每次只有一個事務執行;讀未提交則直接取版本鏈最新的版本資料就行了。

只有在讀已提交(RC)和可重複讀(RR)的隔離級別下,才會使用 MVCC 機制。

  • 讀已提交(RC)時:每次查詢時,都會重新生成 ReadView。


  • 可重複讀(RR)時:在當前事務第一次查詢時,生成 ReadView ,然後一直沿用,直至事務提交,以保證可重複讀。


讀已提交(RC) 和 可重複讀(RR) 的區別是,生成 ReadView 的時機不同。

接下來,我們再來看一個具體的示例,加深理解。


04
   MVCC 的實現示例

假設有一張表,表中有姓名、性別、年齡:











CREATE TABLE `user` (  `id` bigint NOT NULL COMMENT '主鍵',  `name` varchar(20) DEFAULT NULL COMMENT '姓名',  `sex` char(1) DEFAULT NULL COMMENT '性別',  `age` varchar(10) DEFAULT NULL COMMENT '年齡',  `url` varchar(40) DEFAULT NULL,  PRIMARY KEY (`id`),  KEY `suf_index_url` (`name`(3)) USING BTREE) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;

我們在表中插入資料:



INSERT INTO `user` (`id`, `name`, `sex`, `age`, `url`) VALUES ('1', 'mike', '1', '18', ');

插入該記錄的事務 id 為 60:

MySQL MVCC 原理硬核解析,阿里面試官看了都直呼內行

事務 id 為 80、120 的兩條事務,現在要對這條記錄進行 UPDATE 操作:

MySQL MVCC 原理硬核解析,阿里面試官看了都直呼內行

版本鏈在每次進行 update 操作時,將每次的操作詳細記錄在 undo log 中。

每條 undo log 中,都記錄了 rol_pointer 資訊,透過 roll_pointer 進行關聯,可以構成資料的版本鏈

版本鏈的頭節點就是當前記錄最新的值。

如圖:

MySQL MVCC 原理硬核解析,阿里面試官看了都直呼內行

在各個版本中,包含了生成該版本時對應的事務 id。

利用這個記錄的版本鏈來控制併發事務訪問相同記錄的行為,即 MVCC 機制


總結
   

本文重點介紹 MVCC 機制,包括 MVCC 的概念、作用、工作原理、實現示例等。

MVCC 提高資料庫效能和併發效能的關鍵既是面試高頻、也是必知必會,非常重要。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70024923/viewspace-2993612/,如需轉載,請註明出處,否則將追究法律責任。

相關文章