二種MVCC對比分析

文章目錄

  • 前言
  • MVCC
  • Innodb的MVCC
    • 版本鏈
    • 回滾與提交
    • 可見性判斷
  • Oracle的MVCC
    • 版本鏈
  • PostgreSQL的MVCC
    • MVCC實現
    • 可見性判斷
    • 特點

前言

?????MVCC(多版本并發控制,Multi-Version Concurrency Control)是一種數據庫管理系統(DBMS)中用于處理并發訪問的機制。它的核心思想是通過保存數據的多個版本來實現高效的讀寫并發操作,避免事務之間的阻塞,從而提高系統性能, 這篇文章將從幾個數據庫來分析

MVCC

? MVCC是為了在數據庫中, 讀寫不阻塞的情況下, 提供一致性讀的功能

??????在并發操作中,當正在寫時,如果有用戶在讀,這時寫可能只寫了一半,如一行的前半部分剛寫入,后半部分還沒有寫入,這時讀取到的數據行,可能是前半部分是新數據,后半部分是舊數據的不一致的行。解決這個問題的最簡單的辦法是 使用讀寫鎖,寫的時候,不允許讀,正在讀的時候也不允許寫,但這種方法導致讀和寫不能并發。于是,有人就想到了一種能夠讓讀寫并發的方法,這種方法就 是MVCC, MVCC的方法是寫數據時,舊的版本數據并不刪除,并發的讀還能讀到舊的版本數據,這樣就不會有問題了

?????從幾個經典的數據庫來看MVCC可以分為兩種, 一種是基于版本鏈的MVCC, 比如MySQL的Innodb存儲引擎, 還有Oracle數據庫, 這種是將舊數據放在回滾段, 通過一條記錄的回滾指針來找到上一個版本, 另一種是直接將舊版本的數據依然放在當前數據文件中, 比如PostgreSQL

Innodb的MVCC

? ?????對于一條記錄, 除開我們在創建表時規定的列, 還有幾個隱藏字段, 在MVCC我們需要關注這倆個

在這里插入圖片描述

  • trx_id : 創建這條記錄的事務號
  • roll_pointer : 回滾指針, 指向上一個版本

版本鏈

通過回滾指針就可以形成版本鏈

在這里插入圖片描述

  • 在Innodb中存在purge線程,它會查詢那些比現在最老的活動事務還早的undo log,并刪除它們,從而保證undo log文件不至于無限增長。

回滾與提交

  • 正常提交 : 一當事務正常提交時, innodb只需要更改事務狀態為commit即可,不需做其他額外的工作
  • 回滾 : Rollback需要根據當前回滾指針從undo log中找出事務修改前的版本,并恢復。如果事務影響的行非常多,回滾則可能會很慢并且還會加行鎖, 阻塞其他事務,回滾時,也會產生redo日志
  • Innodb的commit效率高,Rollback代價大

可見性判斷

? Innodb判斷一條記錄對于一個事務是否可見是通過讀視圖 ( Read View )來實現的

讀視圖可以看作一個數據結構, 里面有幾個重點字段

  • Create_trx_id : 表示創建該讀視圖的事務id
  • m_ids : 表示創建該讀視圖時, MySQL中活躍的事務id集合
  • min_try_id : 表示創建該讀視圖時, MySQL中活躍的事務id最小值
  • max_try_id : 表示創建該讀視圖時, MySQL中全局最大事務id+1

那么對于一條記錄

  • 如果修改這條記錄的事務id比讀視圖中的min_id還小, 表示這條記錄是在創建該讀視圖之前就修改的, 那么對于當前事務這條數據是可見
  • 如果這個id比讀視圖的Max_id還大, 說明是創建該讀視圖之后才修改的, 那么對于當前事務就是不可見的
  • 如果在兩者之間, 再看讀視圖中的m_ids, 如果這個id存在讀視圖的m_ids里, 說明這條記錄還沒被提交, 那么對于當前事務不可見, 如果不在, 說明該記錄的事務已經被提交, 那么對于當前事務來說就可見

?????在Innodb的事務隔離級別中, 讀提交和可重復讀的區別就是創建讀視圖的時機不同, 讀提交是在該事務每次執行語句都會創建一個讀視圖, 那么在此過程中, 其他事務提交了, 那么就會影響新創建的讀視圖的min_try_id 和m_ids, 使得提交的數據對于當前事務可見, 而可重復讀是在事務啟動時創建一個讀視圖, 整個過程中都用這一個讀視圖, 在此期間, 其他事務提交了, 對于當前事務也是不可見的

Oracle的MVCC

? Oracle也是通過回滾段來實現MVCC的, 但oracle的實現更復雜,更精細一些。

Oracle相對MySQL的Innodb有幾個重點區別

  • Oracle中也有事務ID, 但不是遞增的Undo Segment Number ( 回滾段 Number )+Transaction Table Slot Number ( 槽 Number ) +Wrap ( 槽重用次數), 所以不能通過事務id來判斷事務的執行前后
  • 事務信息并不是記錄在每個數據行上的,而是在塊頭中的ITL槽上,所以相對來說更省空間

在這里插入圖片描述

  • ITL 槽存在數據塊頭部
  • 每條記錄的頭部會有一個字節的數據表示使用了哪一個ITL槽 ( ITL 槽最大255 個)
  • 因為Oracle數據庫的事務ID不能判斷事務的執行前后, 所以為了判斷事務的執行前后引入了一個叫SCN的單調遞增的序號

版本鏈

在這里插入圖片描述

  • Oracle的回滾信息是存在ITL槽中的, 每條記錄的頭部會有一個字節的數據表示使用了哪一個ITL槽, 通過這個ITL槽里的回滾指針, 就可以找到舊版本數據
  • 在回滾段的數據會將舊的ITL槽和數據一起存, 這樣就形成了版本鏈

PostgreSQL的MVCC

??????PostgreSQL數據庫的MVCC不同于基于版本鏈的MVCC, 是沒有回滾段的, 舊數據是存放在原有數據文件中的

  • 為了清理舊數據有一個垃圾回收操作vacuum來做這個事。 同時還有有自動垃圾回收autovacuum
  • 更新操作中新行的物理位置發生了變化使用了HOT技術。如果原有的數據塊之間有空間,舊行與新行之間會建一個鏈接,索引上仍然指向舊的數據行。

MVCC實現

  • 每行上有xmin和xmax兩個系統字段, 當插入一行數據時,將這行上的xmin設置為當前的事務id,而xmax設置為0
  • 當更新一行時,實際上是插入新行,把舊行上的xmax設置為當前事務id,新插入行的xmin設置為當前事務id,新行的xmax設置為0
  • 當刪除一行時,把當前行的xmax設置為當前事務id
  • 當讀到一行時,到commitlog ( 記錄事務是提交還是回滾 ) 中查詢xmin和xmax對應的事務狀態是否是己提交還是回滾了,就能判斷出此行對當前行是否是可見。

在這里插入圖片描述

可見性判斷

?????類似MySQL的innodb, PostgreSQL在執行一條SQL也會生成一個快照, 這里是SnapshotData的數據結構, 里面有幾個重點字段

  • xmin : 己完成的的最大事務
  • xmax : 未開始的事務
  • xip : 當前數據庫中活動的事務id集合

那么對于一條數據

  • 如果數據中的xmin>SnapshotData.xmax 說明這條數據是在當前事務之后的事務插入的, 那么對當前事務不可見
  • 如果數據中的xmin在SnapshotData.xip中, 說明插入這條數據的事務還未提交, 那么對于當前事務不可見
  • 如果數據中的xmin<SnapshotData.xmin, 說明插入這條數據的事務在當前事務之前, 那么就去commit log中查看該事務的狀態, 如果是回滾, 則不可見, 如果是提交, 那么接下來看xmax
    • 如果xmax==0 || xmax in SnapshotData.xip 說明這條數據是當前事務執行前的最新版, 對當前事務可見
    • 如果xmax<SnapshotData.xmin 說明可能存在更新的版本或該數據被刪除, 那么就去commit log中查看該xmax的事務的狀態, 如果是回滾, 那么對當前事務可見, 如果是提交, 說明有更新的版本或者被刪除, 那么這條就對當前事務不可見

特點

  • 事務回滾可以立即完成,無論事務進行了多少操作, 數據可以進行很快更新
  • 舊版本數據需要清理,有autovacuum進程vacuum命令處理

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

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

相關文章

FAST-LIO筆記

1.FAST-LIO FAST-LIO 是一個計算效率高、魯棒性強的激光-慣性里程計系統。該系統通過緊耦合的迭代擴展卡爾曼濾波器&#xff08;IEKF&#xff09;將激光雷達特征點與IMU數據進行融合&#xff0c;使其在快速運動、噪聲較大或環境復雜、存在退化的情況下仍能實現穩定的導航。 1…

C++并發編程完全指南:從基礎到實踐

在當今多核處理器普及的時代&#xff0c;充分利用硬件并發能力已成為高性能編程的關鍵。C11引入的現代并發編程支持使得開發者能夠以標準化、可移植的方式編寫多線程程序。本文將全面介紹C并發編程的各個方面&#xff0c;從基礎概念到實際應用&#xff0c;幫助您掌握這一重要技…

如何使用docker配置ros-noetic環境并使用rviz,gazebo

參考鏈接&#xff1a;【Ubuntu】Docker中配置ROS并可視化Rviz及Gazebo_docker ros-CSDN博客 前言&#xff1a; 其實這個東西是相當必要的&#xff0c;因為我們有時候需要在一臺電腦上跑好幾個項目&#xff0c;每個項目都有不同的依賴&#xff0c;這些依賴沖突搞得人頭皮發麻&…

使用 Java 11 的 HttpClient 處理 RESTful Web 服務

在現代 Web 開發中,與 RESTful Web 服務交互是一項核心任務。Java 作為一種廣泛使用的編程語言,提供了多種處理 HTTP 請求的方法。在 Java 11 之前,開發者通常使用 HttpURLConnection 或第三方庫(如 Apache HttpClient)。然而,這些方法要么過于底層,要么需要額外依賴。J…

JVM——垃圾回收

垃圾回收 在Java虛擬機&#xff08;JVM&#xff09;的自動內存管理中&#xff0c;垃圾回收&#xff08;Garbage Collection, GC&#xff09;是其核心組件之一。它負責回收堆內存中不再使用的對象所占用的內存空間&#xff0c;以供新對象的分配使用。下面我們將深入探討JVM中的…

經典密碼學算法實現

# AES-128 加密算法的規范實現&#xff08;不使用外部庫&#xff09; # ECB模式S_BOX [0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B,0xFE, 0xD7, 0xAB, 0x76, 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0,0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0x…

追蹤大型語言模型的思想(下)(來自針對Claude的分析)

多步推理 正如我們上面所討論的&#xff0c;語言模型回答復雜問題的一種方式就是簡單地記住答案。例如&#xff0c;如果問“達拉斯所在州的首府是哪里&#xff1f;”&#xff0c;一個“機械”的模型可以直接學會輸出“奧斯汀”&#xff0c;而無需知道德克薩斯州&#xff0c;達拉…

【Hive入門】Hive增量數據導入:基于Sqoop的關系型數據庫同步方案深度解析

目錄 引言 1 增量數據導入概述 1.1 增量同步與全量同步對比 1.2 增量同步技術選型矩陣 2 Sqoop增量導入原理剖析 2.1 Sqoop架構設計 2.2 增量同步核心機制 3 Sqoop增量模式詳解 3.1 append模式&#xff08;基于自增ID&#xff09; 3.2 lastmodified模式&#xff08;基…

[Windows] 藍山看圖王 1.0.3.21021

[Windows] 藍山看圖王 鏈接&#xff1a;https://pan.xunlei.com/s/VOPejo0dRLFd38dbpR7XA6djA1?pwddq9v# 由藍山軟件出品的一款免費高清看圖軟件&#xff0c;支持快速查看高清大圖&#xff0c;支持大部分市面圖片格式。 軟件特點 1、體積小巧&#xff0c;圖像顯示效果清晰…

通配符 DNS 記錄:應用場景與相關風險

隨著組織的互聯網基礎設施不斷擴展&#xff0c;其對配置、設置和決策的需求也隨之增加——從選擇一個可靠的名稱服務器&#xff0c;到確定合適的 DNS 記錄類型以及設置合適的 TTL&#xff08;生存時間&#xff09;值。其中一項關鍵決策就是是否要創建通配符 DNS 記錄&#xff0…

快速上手知識圖譜開源庫pykeen教程指南(一)

文章目錄 1 前情提要1.1 AmpliGraph 和 PyKEEN 對比介紹1.2 TransE、ConvE、RotatE幾款模型的差異 2 直接上案例2.1 數據載入&#xff1a;TriplesFactory2.2 模型訓練2.2.1 訓練信息2.2.2 TransE模型可以降維實體、關系的關系 2.3 模型保存與加載、評估2.3.1 保存與模型加載2.3…

飛搭系列 | 獲取彈窗數據,輕松實現回填

前言 飛搭低代碼平臺&#xff08;FeiDa&#xff0c;以下簡稱“飛搭”&#xff09;&#xff0c;為企業提供在線化、靈活的業務應用構建工具&#xff0c;支持高低代碼融合&#xff0c;助力企業低門檻、高效率和低成本地快速應對市場變化&#xff0c;加速復雜業務場景落地。 概要…

Linux如何安裝AppImage程序

Linux如何安裝AppImage程序 文章目錄 Linux如何安裝AppImage程序 在 Linux 中&#xff0c;.AppImage 是一種便攜式的應用程序格式&#xff0c;無需安裝即可運行。 1.賦予該文件可執行權限 可以使用下列命令&#xff0c;賦予可執行權限 # 舉個例子 chmod x /path/to/MyApp.App…

云硬盤的原理

云硬盤是云計算環境中的一種存儲服務&#xff0c;其原理主要涉及數據存儲、數據冗余與容錯、性能優化以及數據安全等方面&#xff0c;以下是具體介紹&#xff1a; 數據存儲 邏輯卷管理&#xff1a;云硬盤通常會將物理存儲設備劃分為多個邏輯卷&#xff0c;每個邏輯卷可以獨立地…

使用 pgrep 殺掉所有指定進程

使用 pgrep 殺掉所有指定進程 pgrep 是一個查找進程 ID 的工具&#xff0c;結合 pkill 或 kill 命令可以方便地終止指定進程。以下是幾種方法&#xff1a; 方法1&#xff1a;使用 pkill&#xff08;最簡單&#xff09; pkill 進程名例如殺掉所有名為 “firefox” 的進程&…

堆排序(算法題)

#include <bits/stdc.h> using namespace std;const int N 100010; // 堆數組的最大容量 int h[N], s; // h[]存儲堆元素&#xff0c;s表示當前堆的大小// 下沉操作&#xff1a;調整以i為根的子樹&#xff0c;維護小頂堆性質 void down(int i) {int t i; /…

極狐GitLab 如何將項目共享給群組?

極狐GitLab 是 GitLab 在中國的發行版&#xff0c;關于中文參考文檔和資料有&#xff1a; 極狐GitLab 中文文檔極狐GitLab 中文論壇極狐GitLab 官網 共享項目和群組 (BASIC ALL) 在極狐GitLab 16.10 中&#xff0c;更改為在成員頁面的成員選項卡上顯示被邀請群組成員&#xf…

用 CodyBuddy 幫我寫自動化運維腳本

我正在參加CodeBuddy「首席試玩官」內容創作大賽&#xff0c;本文所使用的 CodeBuddy 免費下載鏈接&#xff1a;騰訊云代碼助手 CodeBuddy - AI 時代的智能編程伙伴”。 #CodeBuddy首席試玩官 背景 我個人是非常喜歡 Jenkins 自動化部署工具的&#xff0c;之前都是手寫 Jenki…

基于windows安裝MySQL8.0.40

基于windows安裝MySQL8.0.40 基于windows 安裝 MySQL8.0.40&#xff0c;解壓文件到D:\mysql-8.0.40-winx64 在D:\mysql-8.0.40-winx64目錄下創建my.ini文件&#xff0c;并更新一下內容 [client] #客戶端設置&#xff0c;即客戶端默認的連接參數 # 設置mysql客戶端連接服務…

Python小酷庫系列:5個常用的dict屬性化訪問擴展庫

5個常用的dict屬性化訪問擴展庫 嵌套結構高級功能性能綜合建議 在前面我們詳細講解了 Box和 Munch這兩個dict屬性化訪問的擴展庫&#xff0c;總體而言它們主要用于提升配置文件數據、JSON對象數據的可讀性&#xff0c;減少了代碼中雙引號。在這一領域中還有dotmap、addict 和…