多版本并發控制MVCC

?MVCC(Multi-Version Concurrency Control,多版本并發控制)。是一個在數據庫管理系統中用于處理并發控制的核心技術。理解它對于深入掌握數據庫(尤其是 InnoDB、PostgreSQL 等)的工作原理至關重要。

1. 什么是 MVCC?

MVCC 的全稱是?多版本并發控制

核心思想:在數據庫中,同一份數據可以保留多個歷史版本。當事務需要讀取數據時,它會根據一定的規則(比如事務的開始時間)看到一個特定的、一致性的“快照”(Snapshot),而不是直接讀取最新的、可能還未提交的數據。寫操作則會創建一個新版本的數據。

你可以把它想象成一個高效的版本控制系統(如 Git):

  • 讀操作:就像?git checkout?到某個特定的 commit 版本,你看到的是那個時間點的完整項目狀態,即使之后有新的提交,你的視圖也不會變。
  • 寫操作:就像創建一個新的?commit,它不會覆蓋舊的?commit,而是在舊版本的基礎上生成一個新版本。

通過這種方式,讀操作和寫操作可以不再互相阻塞,從而極大地提高了數據庫的并發性能。


2. 為什么需要 MVCC?

在傳統的數據庫并發控制中,主要使用兩種機制:

  1. 鎖機制

    • 讀-寫沖突:當一個事務在讀取一行數據時,會給它加上共享鎖(S鎖)。另一個事務如果想修改這行數據,需要加排他鎖(X鎖),但 S 鎖和 X 鎖互斥,所以寫事務必須等待讀事務完成。反之亦然,寫事務會阻塞讀事務。
    • 問題:并發度低。讀和寫操作串行化,性能很差。
  2. 基于時間戳的排序

    • 所有操作按時間戳排序執行,如果操作沖突,則回滾其中一個事務。
    • 問題:事務沖突率高,回滾頻繁,性能同樣不理想。

MVCC 的出現就是為了解決這些問題,它提供了一種“樂觀”的并發控制方式:

  • 讀寫不沖突:讀數據(快照讀)不會阻塞寫數據,寫數據也不會阻塞讀數據。這是 MVCC 最大的優勢。
  • 非鎖定讀:大多數情況下,普通的?SELECT?查詢不需要加鎖,避免了鎖的開銷和死鎖的風險。
  • 實現事務隔離:MVCC 是實現數據庫事務隔離級別(特別是?READ COMMITTED?和?REPEATABLE READ)的基礎。

3. MVCC 是如何工作的?

MVCC 的實現依賴于三個關鍵組件:隱藏列Undo Log?和?Read View。我們以最經典的?MySQL InnoDB 存儲引擎為例來講解。

a. 隱藏列

InnoDB 會為每一行數據額外添加三個隱藏的字段:

  • DB_TRX_ID?(6字節):?最后修改該行的事務ID。記錄了最后一次對這行記錄進行?INSERT?或?UPDATE?的事務ID。每次事務修改一行,這個字段都會被更新。
  • DB_ROLL_PTR?(7字節):?回滾指針。它指向該行上一個版本的數據在 Undo Log 中的位置。通過這個指針,可以形成一個“版本鏈”,把一個數據行的所有歷史版本串聯起來。
  • DB_ROW_ID?(6字節):?隱藏的行ID。一個單調遞增的ID,當表沒有顯式主鍵時,InnoDB會用它來生成一個聚集索引。

版本鏈示例
假設一行數據被事務 10、事務 20 依次修改。

  1. 初始狀態:事務 10 插入一行數據。
    • DB_TRX_ID = 10
    • DB_ROLL_PTR = null?(因為是第一個版本)
  2. 事務 20 修改:事務 20 更新了這行數據。
    • InnoDB?不會直接覆蓋舊數據,而是:
      1. 將舊版本的數據(DB_TRX_ID=10?的版本)復制到 Undo Log 中。
      2. 在原位置創建一個新版本的數據行。
      3. 更新新版本的字段:DB_TRX_ID = 20
      4. 更新新版本的?DB_ROLL_PTR,讓它指向 Undo Log 中舊版本的位置。
    • 現在,通過新版本的?DB_ROLL_PTR,我們可以找到舊版本,形成一條?版本鏈最新版本(20) -> 舊版本(10)
b. Undo Log

Undo Log 主要有兩個作用:

  1. 事務回滾:當一個事務需要回滾時,可以利用 Undo Log 中記錄的舊版本數據,將數據恢復到修改之前的狀態。
  2. 構建版本鏈:如上所述,它存儲了數據行的歷史版本,是 MVCC 實現多版本的關鍵。當需要讀取某個歷史版本時,就可以從這里獲取。
c. Read View(讀視圖)

Read View 是事務在執行快照讀(普通的?SELECT)時,動態生成的一個“可見性判斷”標準。它決定了當前事務能看到版本鏈上的哪個版本。

Read View 主要包含以下幾個重要屬性:

  • creator_trx_id: 創建該 Read View 的事務的 ID。
  • trx_ids: 創建 Read View 時,當前系統中所有活躍的(未提交的)讀寫事務的 ID 列表。
  • up_limit_id:?trx_ids?列表中事務 ID 的最小值。如果版本鏈上某個版本的?DB_TRX_ID?小于?up_limit_id,則表示這個版本在創建 Read View 之前已經提交,所以對當前事務是可見的
  • low_limit_id: 創建 Read View 時,系統應該分配給下一個事務的 ID。如果版本鏈上某個版本的?DB_TRX_ID?大于或等于?low_limit_id,則表示這個版本是在創建 Read View 之后才開啟的事務中修改的,所以對當前事務是不可見的

4. MVCC 如何解決并發問題?

現在,我們把這三個組件結合起來,看看一個?SELECT?語句是如何利用 MVCC 找到它應該看到的數據版本的。我們以?InnoDB 的?REPEATABLE READ(可重復讀)隔離級別為例。

核心判斷流程
當一個事務(假設 ID 為?T1)執行?SELECT?時,它會獲取一個 Read View。然后,它會從版本鏈的最新版本開始,逐個版本地應用以下規則,直到找到一個可見的版本:

  1. 檢查?DB_TRX_ID?是否是自己創建的?

    • 如果?DB_TRX_ID == creator_trx_id,說明這行數據是本事務自己修改的,可見
  2. 檢查?DB_TRX_ID?是否小于?up_limit_id

    • 如果?DB_TRX_ID < up_limit_id,說明修改這個版本的事務在當前事務開始前就已經提交了,可見
  3. 檢查?DB_TRX_ID?是否大于或等于?low_limit_id

    • 如果?DB_TRX_ID >= low_limit_id,說明修改這個版本的事務是在當前事務開始之后才啟動的,不可見。需要根據?DB_ROLL_PTR?去 Undo Log 中查找上一個版本,然后重復整個判斷流程。
  4. 檢查?DB_TRX_ID?是否在?trx_ids?列表中?

    • 如果?up_limit_id <= DB_TRX_ID < low_limit_id,則需要判斷?DB_TRX_ID?是否在活躍事務列表?trx_ids?中。
    • 如果在:說明修改這個版本的事務在當前事務創建 Read View 時還未提交,不可見。需要去 Undo Log 中找上一個版本。
    • 如果不在:說明修改這個版本的事務在當前事務創建 Read View 時已經提交了,可見

最終:如果遍歷完整個版本鏈都找不到可見的版本,說明這行數據對當前事務是不可見的(比如被其他事務刪除了)。

REPEATABLE READ?vs?READ COMMITTED?的關鍵區別
  • REPEATABLE READ?(可重復讀)

    • 事務中第一次執行?SELECT?時,會創建一個 Read View,之后該事務內的所有?SELECT?都復用這個 Read View
    • 效果:確保了在同一個事務中,多次讀取同一數據的結果是一致的,因為判斷可見性的標準(Read View)從未改變。這就是“可重復讀”的由來。
  • READ COMMITTED?(讀已提交)

    • 事務中每次執行?SELECT?時,都會重新創建一個新的 Read View
    • 效果:每次讀取都能看到其他已提交事務所做的最新修改。因為每次的 Read View 都是最新的,up_limit_id?和?trx_ids?都會更新,所以之前不可見的版本可能就變得可見了。

5. MVCC 的優缺點

優點
  1. 高并發性:讀寫操作不阻塞,極大地提高了數據庫的并發讀寫性能。
  2. 非鎖定讀:避免了讀操作加鎖帶來的開銷和死鎖風險。
  3. 實現一致性讀:為不同隔離級別提供了基礎,保證了事務的隔離性。
缺點
  1. 存儲空間開銷:需要維護多個版本的數據,Undo Log 會占用額外的存儲空間。對于長事務或更新頻繁的表,Undo Log 可能會變得非常大。
  2. 管理開銷:需要額外的邏輯來管理版本鏈、創建和判斷 Read View,增加了數據庫的復雜性。
  3. 行版本清理:需要后臺線程(如 InnoDB 的 Purge 線程)定期清理已經不再需要的舊版本數據(即沒有事務再需要訪問它們),否則 Undo Log 會無限增長。這個清理過程本身也消耗資源。
  4. 并非萬能:MVCC 主要解決的是?SELECT?的并發問題。對于?UPDATEDELETE?之間的沖突,仍然需要使用(比如行鎖、間隙鎖、Next-Key Locks)來保證數據的一致性和防止幻讀。

6. MVCC 與隔離級別的關系

隔離級別MVCC 如何工作能解決的問題
READ UNCOMMITTED?(讀未提交)基本不使用 MVCC。直接讀取最新的數據,即使它未提交。
READ COMMITTED?(讀已提交)每次?SELECT?都創建新的 Read View。只能讀到已提交的數據。解決臟讀
REPEATABLE READ?(可重復讀)事務中第一次?SELECT?創建 Read View,后續復用。保證同一事務內多次讀取結果一致。解決臟讀、不可重復讀
(在 InnoDB 中,結合 Next-Key Locks 還能解決幻讀)
SERIALIZABLE?(可串行化)基本不使用 MVCC 的快照讀。所有?SELECT?語句都會隱式地轉換為?SELECT ... LOCK IN SHARE MODE,即加共享鎖。讀寫操作都互相阻塞。解決所有并發問題(臟讀、不可重復讀、幻讀)

7. 總結

MVCC 是一種優雅而強大的并發控制技術,其精髓在于“用空間換時間,用版本換鎖”。

  • 核心:通過為數據維護多個版本,讓讀操作訪問歷史快照,寫操作創建新版本。
  • 關鍵組件:隱藏列(DB_TRX_ID,?DB_ROLL_PTR)構建版本鏈,Undo Log 存儲歷史版本,Read View 定義可見性規則。
  • 目的:實現讀寫不阻塞,提高并發性能,并作為實現數據庫事務隔離級別的基礎。
  • 應用:廣泛應用于現代主流數據庫,如?MySQL InnoDBPostgreSQLOracle?等。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/97097.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/97097.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/97097.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

嵌入式第三十七天(TCP補充,應用層協議(HTTP))

一.TCP機制二.HTTP協議1.2.3.4.5.6.7.8.#ifndef _HEAD_H #define _HEAD_H#include<stdio.h> #include<stdlib.h> #include<string.h> #include<unistd.h> #include<arpa/inet.h> #include<sys/socket.h>#endif#include "head.h"…

Elasticsearch核心配置詳解與優化

Elasticsearch 的核心配置文件主要用于控制節點行為、集群設置、資源分配和日志記錄等關鍵功能。主要配置文件通常位于 ES_HOME/config 目錄下&#xff0c;以下是三個最核心的配置文件及其詳細說明&#xff1a; 1. elasticsearch.yml 核心集群與節點配置 這是最重要的配置文件…

機器學習框架下:金價近3400關口波動,AI量化模型對PCE數據的動態監測與趨勢預測

摘要&#xff1a;本文通過AI多因子模型&#xff0c;結合宏觀經濟數據、政策動態及市場情緒因子&#xff0c;分析黃金價格波動機制及關鍵驅動要素。基于量化策略與自然語言處理技術&#xff0c;對美聯儲獨立性爭議、美債收益率曲線形態及PCE通脹數據等核心變量進行動態建模&…

【Redis#8】Redis 數據結構 -- Zset 類型

一、引言 定義&#xff1a;有序集合&#xff08;Zset&#xff09;是Redis中的一種數據結構&#xff0c;它結合了哈希表和跳躍列表的特性。每個 member 都有一個分數(score)&#xff0c;根據這個分數進行排序。 特點&#xff1a; member 不能重復&#xff0c;但分數可以相同&…

Postman 模擬mcp tool調用過程

文章目錄 初始化調用 mcp server使用modelcontextprotocol 的java sdk編寫 初始化 1.網頁訪問http://localhost:8090/sse,此頁面保持開啟,會不斷接收到sse事件. 會返回一個endpoint,例如/mcp/message?sessionId111 2.初始化請求,postman發送post請求 url:http://localhost:…

init.usb.configfs.rc的USB動態配置

1. 什么是ConfigFSConfigFS 是 Linux 內核提供的一種用戶空間可配置的偽文件系統在Linux內核中一個設備&#xff08;如手機&#xff09;作為USB從設備時&#xff0c;成為一個“Gadget”。路徑&#xff1a;/config/usb_gadget/&#xff0c;g1表示系統重第一個USB Gadget的配置實…

廣東省省考備考(第八十九天8.28)——判斷推理(聽課后強化訓練)

判斷推理&#xff1a;定義判斷 錯題解析 第一步&#xff1a;找出定義關鍵詞。 “為了明確所承運的貨物是否發生了殘損&#xff0c;以及殘損責任是否屬于船方”。 第二步&#xff1a;逐一分析選項。 A項&#xff1a;甲船向商檢機構申請檢查船舶卸貨前艙口、風筒的封蓋和封識情況…

【C++】C++11的右值引用和移動語義

各位大佬好&#xff0c;我是落羽&#xff01;一個堅持學習進步的學生。 如果您覺得我的文章還不錯&#xff0c;歡迎多多互三分享交流&#xff0c;一起學習進步&#xff01; 也歡迎關注我的blog主頁: 落羽的落羽 文章目錄一、C11簡介二、左值和右值是什么三、左值引用與右值引…

Logic Error: 如何識別和修復邏輯錯誤

邏輯錯誤是指程序中的代碼在語法上是正確的&#xff0c;但在執行時沒有按預期工作。這種錯誤可能導致程序輸出錯誤的結果或行為異常。邏輯錯誤通常比語法錯誤更難檢測&#xff0c;因為它們不會產生編譯或解釋錯誤。本文將詳細介紹如何識別和修復邏輯錯誤。一、識別邏輯錯誤1. 理…

TUN模式端口沖突 啟動失敗如何解決?

從日志信息來看&#xff0c;TUN模式啟動失敗是由于端口沖突導致的。 具體來說&#xff0c;Xray在嘗試監聽10808端口時失敗了&#xff0c;因為該端口已經被其他進程占用。 錯誤信息分析 Failed to start: app/proxyman/inbound: failed to listen TCP on 10808 > transport/i…

如何調試一個EVM合約:實戰操作 + 常見報錯說明

在Solidity開發過程中&#xff0c;大多數開發者最常遇到的問題不是“代碼寫不了”&#xff0c;而是“代碼部署了&#xff0c;但行為不對”。本篇文章將帶你梳理一套完整的EVM智能合約調試流程&#xff0c;并附上幾類真實常見報錯場景及排查方法&#xff0c;適用于Hardhat、Remi…

使用Wireshark分析自助終端機網絡數據

如果是明文還好&#xff0c; 是密文就沒辦法了。工具.1自助終端機.2組裝結構主流架構選擇?B/S架構?&#xff1a;通過Web應用調用本地硬件插件&#xff0c;開發速度快但依賴瀏覽器兼容性。 ??C/S架構?&#xff1a;直接調用硬件驅動&#xff0c;交互響應快但更新維護復雜。 …

數學建模——馬爾科夫鏈(Markov Chain Model)

數學建模——馬爾科夫鏈&#xff08;Markov Chain Model&#xff09;一、馬爾可夫鏈的定義1. 狀態與狀態空間2. 無后效性&#xff08;馬爾科夫性&#xff09;?3. 轉移概率與轉移概率矩陣&#xff08;1&#xff09;一步轉移概率&#xff08;2&#xff09;轉移概率矩陣二、馬爾科…

《拉康精神分析學中的欲望辯證法:能指的拓撲學與主體的解構性重構》

在當代人文思想圖譜中&#xff0c;雅克拉康以語言學為利刃對弗洛伊德理論進行的結構性重鑄構成了20世紀最具顛覆性的理論創造之一。這位被譽為"法國弗洛伊德"的思想巨匠通過"回到弗洛伊德"的口號&#xff0c;實則完成了對精神分析學的哥白尼式革命——將主…

數字時代下的智能信息傳播引擎

在商場、樓宇、交通樞紐等公共場所&#xff0c;數字廣告機已成為信息傳播的重要載體。其背后的廣告機系統&#xff0c;是一套集硬件控制、內容管理、網絡傳輸與數據分析于一體的綜合技術解決方案&#xff0c;正推動傳統靜態廣告向動態化、交互化、智能化方向演進。系統架構與核…

文獻閱讀筆記:KalmanNet-融合神經網絡和卡爾曼濾波的部分已知動力學狀態估計

文獻閱讀筆記&#xff1a;KalmanNet-融合神經網絡和卡爾曼濾波的部分已知動力學狀態估計摘要一、研究背景1.1 狀態估計問題的重要性1.2 傳統方法的局限&#xff1a;非線性與模型不確定性非線性問題噪聲統計未知問題1.3 數據驅動方法的興起與局限1.4 KalmanNet&#xff1a;混合方…

使用EasyExcel根據模板導出文件

文章目錄概要工具類核心功能核心代碼解析模板導出核心方法文件下載處理HTTP響應設置文件下載處理使用示例概要 在企業級應用開發中&#xff0c;Excel數據導出是一個常見的需求。本文實現一個基于阿里巴巴EasyExcel庫實現的根據模板導出文件的工具類&#xff0c;它通過預定義的…

【AI基礎:神經網絡】19、機器學習實戰:徑向基函數神經網絡(RBFN)指南

一、引言:為什么RBFN是神經網絡中的“局部專家”? 在機器學習領域,神經網絡的“全局逼近”與“局部逼近”一直是兩大核心思路。像我們熟悉的多層感知機(MLP),使用Sigmoid、ReLU等全局激活函數,每個神經元都會對整個輸入空間產生響應——就像“全員參與”處理所有數據,…

Linux 性能調優實戰:CPU、磁盤 I/O、網絡與內核參數

前言 一、CPU 資源調優 1. 調整進程優先級&#xff08;nice/renice&#xff09; 2. 設置 CPU 親和力&#xff08;taskset&#xff09; 3. 查看 CPU 信息 4. 使用 vmstat 分析系統瓶頸 二、磁盤 I/O 調優 1. ulimit 資源限制 2. 磁盤速度測試 三、內核參數調優 1. 常用…

【進階篇第五彈】《詳解存儲過程》從0掌握MySQL中的存儲過程以及存儲函數

文章目錄存儲過程一、基本語法(1)創建存儲過程(2)調用存儲過程(3)查看存儲過程(4)刪除存儲過程(5)設置結束符(6)參數二、變量(1)系統變量(2)用戶自定義變量(3)局部變量三、基本語句(1)if判斷(2)case(3)while循環(4)repeat(5)loop循環四、游標五、條件處理程序六、存儲函數存儲過…