如何理解MySql的MVCC機制

MVCC是什么

MySQL的MVCC機制,全稱為多版本并發控制(Multi-VersionConcurrency Control),是一種提高數據庫并發性能的技術。MVCC的主要目的是在保證數據一致性的同時,提高數據庫的并發性能。

它通過為每個讀操作創建數據的快照來實現這一點,這樣即使在數據被其他事務修改的同時,讀操作也能夠看到一致的數據視圖。這種機制避免了同一個數據在不同事務之間的競爭,從而提高了系統的并發性能。

MVCC在MySQL中的實現主要是為了解決讀寫沖突問題,使得即使在有讀寫沖突的情況下,也能做到不加鎖,非阻塞并發讀。MVCC通過維護數據的不同版本來實現這一點,每個事務都可以看到適合自己版本的數據,而不會被其他事務的修改所影響。

MVCC適用范圍

在MySQL中,MVCC只在讀取已提交(Read Committed)和可重復讀(Repeatable Read)兩個事務級別下有效。底層通過Undolog日志中的版本鏈ReadView一致性視圖來實現的。MVCC就是在多個事務同時存在時,SELECT語句找尋到具體是版本鏈上的哪個版本,然后在找到的版本上返回其中所記錄的數據的過程。

當前讀:總是讀取當前最新的數據。

像select?lock?in?share?mode(共享鎖),?select?for?update?;?update,?insert?,delete(排他鎖)這些操作都是一種當前讀

快照讀:像不加鎖的select操作就是快照讀,即不加鎖的非阻塞讀;快照讀的前提是隔離級別不是串行級別串行級別下的快照讀會退化成當前讀;之所以出現快照讀的情況,是基于提高并發性能的考慮,快照讀的實現是基于多版本并發控制,即MVCC,可以認為MVCC是行鎖的一個變種,但它在很多情況下,避免了加鎖操作,降低了開銷;既然是基于多版本,即快照讀可能讀到的并不一定是數據的最新版本,而有可能是之前的歷史版本

update delete一定是當前讀

表隱藏字段?

  • DB_ROW_ID:隱藏主鍵,MySQL的B+樹索引特性要求每個表必須要有一個主鍵。如果沒有設置的話,會自動尋找第一個不包含NULL的唯一索引列作為主鍵。如果還是找不到,就會在這個DB_ROW_ID上自動生成一個唯一值,以此來當作主鍵(該列和MVCC的關系不大);

  • DB_TRX_ID:最后一次事務ID,記錄的是當前事務在做INSERT或UPDATE語句操作時的事務ID(DELETE語句被當做是UPDATE語句的特殊情況,后面會進行說明);

  • DB_ROLL_PTR:回滾指針,通過它可以將不同的版本串聯起來,形成版本鏈。相當于鏈表的next指針。這個指針實際就是指向undolog的快照對應版本的數據。

MVCC的工作流程?

1. 事務開始時,獲取一個唯一的事務ID。

2. 當進行讀取操作時,數據庫會創建一個Read View,其中包含了當前系統中活躍事務的信息。

3. 讀取數據時,數據庫會根據Read View中的信息來確定哪個版本的數據是可見的。

4. 如果當前版本的數據不可見,數據庫會通過undo日志找到合適的歷史版本。

MVCC與鎖機制的比較

MVCC和鎖機制都是并發控制的手段,但它們在不同的場景下有不同的應用。鎖機制通過在數據上加鎖來保證事務的隔離性,是一種悲觀鎖的實現。而MVCC通過維護數據的多個版本來實現非鎖定讀取,是一種樂觀鎖的實現。

無鎖架構:COW思想

Copy-On-Write(COW,寫時復制)是一種常見的并發編程思想。

Copy-On-Write基本思想是,當多個線程需要對共享數據進行修改時,不直接在原始數據上進行操作,而是先將原始數據復制一份(即寫時復制),然后在副本上進行Write。

Copy-On-Write 通過操作寫操作副本,引入局部無鎖架構,解決并且處理之間的數據沖突,提高了并發性能。

Copy-On-Write的實現步驟如下:

  1. 讀取數據:多個線程同時讀取共享數據時,它們可以直接訪問原始數據,而不需要復制。因為讀取操作不會修改數據,所以可以安全地共享原始數據。

  2. 寫入數據:當某個線程需要修改共享數據時,首先會將原始數據進行復制(即寫時復制),然后在副本上進行修改。這樣做的好處是,其他線程仍然可以繼續讀取原始數據,不受寫入線程的影響。

  3. 更新引用:寫入線程完成修改后,會更新共享數據的引用,使得其他線程后續訪問時可以獲取到最新的數據副本。

Copy-On-Write的優點包括:

  • 線程安全:通過復制數據副本并在副本上進行修改,避免了多線程并發修改原始數據時的數據沖突問題,從而提高了線程安全性。

  • 減少鎖競爭:由于讀取操作不需要加鎖,所以可以減少鎖競爭,提高了并發性能。

  • 節省內存:只有在有寫入操作時才會進行數據復制,而讀取操作可以共享原始數據,因此可以節省內存空間。

然而,Copy-On-Write也有一些缺點,主要是由于數據復制和更新引用所帶來的額外開銷,可能會導致內存和性能方面的消耗增加。因此,適用場景需要根據具體情況進行評估和選擇。

COW思想寫操作之間是要互斥的,并且每次寫操作都會有一次copy,所以只適合讀大于寫的情況。所以,COW思想 專門用于優化讀的次數遠大于寫次數的場景。比如,Java的 并發容器CopyOnWriteArrayList。

Java中的CopyOnWriteArrayList

CopyOnWriteArrayList 是jdk1.5以后并發包中提供的一種并發容器,寫操作通過創建底層數組的新副本來實現,是一種讀寫分離的并發策略,我們也成為“寫時復制容器”。

public boolean add(E e) {//加鎖,對寫操作保證線程安全final ReentrantLock lock = this.lock;lock.lock();try {Object[] elements = getArray();int len = elements.length;//拷貝原容器,長度為原容器+1Object[] newElements = Arrays.copyOf(elements, len + 1);//在新副本執行添加操作newElements[len] = e;//底層數組指向新的數組setArray(newElements);return true;} finally {lock.unlock();}
}

CopyOnWriteArrayList底層實現添加的原理是先copy出一個容器(可以簡稱副本),再往新的容器里添加這個新的數據,最后把新的容器的引用地址賦值給了之前那個舊的的容器地址,但是在添加這個數據的期間,其他線程如果要去讀取數據,仍然是讀取到舊的容器里的數據。

MVCC核心ReadView

先來思考如下的問題:

如果T1事務要查詢id=1的一條行數據,此時這條行數據正在被T2事務修改,那也就代表著這條數據可能存在多個舊版本數據,T1事務在查詢時,應該讀這條數據的哪個版本呢?

此時就需要用到ReadView,用它來做多版本的并發控制,根據查詢的時機,來選擇一個當前事務可見的舊版本數據讀取。

什么是ReadView呢??

當一個事務在嘗試讀取一條數據時,MVCC基于當前MySQL的運行狀態生成的快照,也被稱之為讀視圖,即ReadView,在這個快照中記錄著當前所有活躍事務的ID(活躍事務是指還在執行的事務,即未結束(提交/回滾)的事務)。

ReadView是事務在進行快照讀的時候生成的記錄快照, 可以幫助我們解決可見性問題的。

ReadView的核心屬性

當一個事務啟動后,首次執行select操作時,MVCC就會生成一個數據庫當前的ReadView

通常而言,一個事務與一個ReadView屬于一對一的關系(不同隔離級別下也會存在細微差異),ReadView一般包含4個核心屬性:

我們假設目前數據庫中共有T1~T6這6個事務,T1、T2、T4、T6還在執行,T3已經回滾,T5已經提交,

此時當有一條查詢語句執行時,就會利用MVCC機制生成一個ReadView,由于在MySQL中單純由一條select語句組成的事務并不會分配事務ID,因此默認為0,所以目前這個ReadView的信息如下:

ReadView的讀取規則
?

訪問某條記錄的時候如何判斷該記錄是否可見,具體規則如下:

  • 如果被訪問版本的?事務ID = creator_trx_id,那么表示當前事務訪問的是自己修改過的記錄,那么該版本對當前事務可見;

  • 如果被訪問版本的?事務ID < up_limit_id,那么表示生成該版本的事務在當前事務生成 ReadView 前已經提交,所以該版本可以被當前事務訪問。

  • 如果被訪問版本的?事務ID > low_limit_id?值,那么表示生成該版本的事務在當前事務生成 ReadView 后才開啟,所以該版本不可以被當前事務訪問。

  • 如果被訪問版本的?事務ID在 up_limit_id和m_low_limit_id之間,那就需要判斷一下版本的事務ID是不是在 trx_ids 列表中,如果在,說明創建 ReadView 時生成該版本的事務還是活躍的,該版本不可以被訪問;

  • 如果不在,說明創建 ReadView 時生成該版本的事務已經被提交,該版本可以被訪問。

上面這種圖,網上有上萬篇文章, 都是抄來抄去, 沒有一篇文章做了總結和簡化。

關于這個對比規則,由于邏輯復雜,導致盡管大家看了那些文章,甚至看了很多視頻,還是不能理解透徹, 迷迷糊糊的,面試的時候 說不清楚,也很容易忘了。

尼恩團隊看不下去,用咱們的雄厚技術實力(洪荒之力), 給大家來總結和簡化。

具體如下:

?

?

?

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

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

相關文章

【高中數學/三角函數】已知:x,y皆為實數,且4x^2+y^2+xy=1 求:2x+y的最大值

【問題】 已知&#xff1a;x,y皆為實數&#xff0c;且4x^2y^2xy1 求&#xff1a;2xy的最大值 【問題來源】 https://www.ixigua.com/7289764285772497448?logTag0d228277f3a8e049ab6d 【解答】 解&#xff1a; 由4x^2y^2xy1 可得 15/4*x^21/4*x^2xyy^21 得到(15開方/…

智能版面設計:指令跟隨模型在自動布局規劃中的應用

在廣告行業一個吸引人的視覺布局能夠顯著提升信息的傳播效果。但對于非專業設計師來說&#xff0c;創建既美觀又功能性強的布局常常是一項挑戰。他們往往缺乏必要的設計技能、審美訓練或資源來快速實現創意構想。傳統的設計軟件和在線工具雖然提供了一些模板和指導&#xff0c;…

0702_ARM6

練習&#xff1a; 中斷實驗 main.c #include "key.h" int main() {//初始化rcc gpiohal_key_rcc_gpio_init();//初始化extihal_key_exti_init();//初始化gichal_key_gic_init();while(1){}return 0; }key.c #include "key.h"//GPIOF初始化 void hal_key_…

Linux的一些雜項函數總結

getopt_long 解析命令行。 參考&#xff1a; C語言linux getopt_long()函數&#xff08;命令行解析&#xff09;&#xff08;getopt、getopt_long_only&#xff09;&#xff08;短選項 -&#xff0c;長選項 --&#xff09;&#xff08;option結構體&#xff09;&#xff08;opt…

vue3-openlayers marker 光暈擴散(光環擴散)(postrender 事件和 render 方法)

本篇介紹一下使用 vue3-openlayers marker 光暈擴散&#xff08;光環擴散&#xff09;&#xff08;postrender 事件和 render 方法&#xff09; 1 需求 marker 光暈擴散&#xff08;光環擴散&#xff09; 2 分析 marker 光暈擴散&#xff08;光環擴散&#xff09;使用 post…

中級java每日一道面試題-2024年7月2日

題目&#xff1a; 請解釋一下 Java 中的線程安全問題&#xff0c;并提供一些常見的解決方法。 答案&#xff1a; 線程安全問題是指在多線程環境下&#xff0c;多個線程同時訪問共享資源時可能出現的數據不一致或錯誤的情況。這可能導致程序的不可預測性和錯誤的結果。 常見的…

徐州三線服務器租用的優勢有哪些?

對于單線服務器與雙線服務器來說&#xff0c;三線服務器是能夠同時擁有電信、聯通和移動三條線路的服務器&#xff0c;同時也被稱為三線路由器或者是三線寬帶路由器&#xff0c;有著三個獨立的網卡和三個IP地址&#xff0c;使用戶無論是通過哪些線路連接都能夠進入服務器&#…

android.bp 靜態庫 依賴 動態庫

在Android平臺上&#xff0c;使用Android.bp文件來定義和構建Android靜態庫&#xff08;.so文件&#xff09;和動態庫&#xff08;.so文件&#xff09;之間的依賴關系是很常見的。以下是一個簡單的例子&#xff0c;展示了如何在Android.bp文件中定義一個靜態庫&#xff0c;它依…

SPI NAND、SD NAND和eMMC對比—MK米客方德

目錄 1. 容量: 2.封裝類型&#xff1a; 3.速度: 4.性能: 5.壽命: 6. 使用方式: 7. 其他優缺點: 8.常見應用場景: 1. 容量: SPI NAND通常提供從幾百MB到幾GB的存儲容量。 SD NAND的容量覆蓋范圍比SPI NAND更廣&#xff0c;從幾GB到幾十GB不等。 eMMC的容量范圍更大&a…

代碼隨想錄第41天|動態規劃

322. 零錢兌換 dp[j] : 最小硬幣數量, j 為金額(相當于背包空間)遞推公式 : dp[j] min(dp[j - coins[i]] 1, dp[j])初始化: 需要一個最大值, 避免覆蓋, dp[0] 0遍歷順序: 錢幣有序無序不影響, 因為求解最小個數, 結果相同(先遍歷物品后背包, 先背包后物品都可) class Solut…

【chatgpt】兩層gcn提取最后一層節點輸出特征,如何自定義簡單數據集

文章目錄 兩層gcn&#xff0c;提取最后一層節點輸出特征&#xff0c;10個節點&#xff0c;每個節點8個特征&#xff0c;連接關系隨機生成&#xff08;無全連接層&#xff09;如何計算MSE 100個樣本&#xff0c;并且使用批量大小為32進行訓練第一個版本定義數據集出錯&#xff0…

怎樣在《語文世界》期刊上發表論文?

怎樣在《語文世界》期刊上發表論文&#xff1f; 《語文世界》知網國家級 1.5-2版 2500字符左右 正常收25年4-6月版面 可加急24年內&#xff08;初中&#xff0c;高中&#xff0c;中職&#xff0c;高職&#xff0c;大學均可&#xff0c;操作周期2個月左右&#xff09; 《語文世…

【084】基于SpringBoot實現的家鄉特色推薦系統

系統介紹 視頻演示 點擊查看演示視頻 基于SpringBoot實現的家鄉特色推薦系統主要采用SpringBootVue進行開發&#xff0c;系統整體分為管理員、用戶兩種角色&#xff0c;主要功能包括首頁&#xff0c;個人中心&#xff0c;用戶管理&#xff0c;文章分類管理&#xff0c;文章分…

C語言結構體深入解析【結構體嵌套結構體,結構體變量和指針,結構體和函數,計算結構體大小,結構體數組,結構體成員的訪問,結構體與聯合】

C語言結構體深入解析 目錄 C語言結構體深入解析前言結構體的定義結構體在內存中的表示結構體變量初始化直接定義并初始化使用自己定義的結構體變量初始化新變量結構體數組初始化 結構體中嵌套結構體結構體成員訪問點操作符(.)箭頭操作符(->) 結構體變量和指針結構體指針定義…

TensorFlow代碼邏輯 vs PyTorch代碼邏輯

文章目錄 一、TensorFlow&#xff08;一&#xff09;導入必要的庫&#xff08;二&#xff09;加載MNIST數據集&#xff08;三&#xff09;數據預處理&#xff08;四&#xff09;構建神經網絡模型&#xff08;五&#xff09;編譯模型&#xff08;六&#xff09;訓練模型&#xf…

@RequestMapping屬性詳解及案例演示

RequestMapping源碼 Target({ElementType.TYPE, ElementType.METHOD}) Retention(RetentionPolicy.RUNTIME) Documented Mapping public interface RequestMapping {String name() default "";AliasFor("path")String[] value() default {};AliasFor(&quo…

智能寫作與痕跡消除:AI在創意文案和論文去痕中的應用

作為一名AI愛好者&#xff0c;我積累了許多實用的AI生成工具。今天&#xff0c;我想分享一些我經常使用的工具&#xff0c;這些工具不僅能幫助提升工作效率&#xff0c;還能激發創意思維。 我們都知道&#xff0c;隨著技術的進步&#xff0c;AI生成工具已經變得越來越智能&…

簡單分享 for循環,從基礎到高級

1. 基礎篇&#xff1a;Hello, For Loop! 想象一下&#xff0c;你想給班上的每位同學發送“Hello!”&#xff0c;怎么辦&#xff1f;那就是for循環啦&#xff0c; eg&#xff1a;首先有個名字的列表&#xff0c;for循環取出&#xff0c;分別打印 names ["Alice", …

Apache APISIX 介紹

Apache APISIX 是一個動態、實時、高性能的云原生API網關&#xff0c;屬于Apache軟件基金會旗下的項目。以下是對Apache APISIX的詳細介紹&#xff1a; 一、基本概述 定義&#xff1a;Apache APISIX是一個提供豐富流量管理功能的云原生API網關。功能&#xff1a;包括負載均衡…

git出現Permission denied問題

Warning: Permanently added ‘icode.baidu.com,10.11.81.103’ (RSA) to the list of known hosts. Permission denied (baas,keyboard-interactive,publickey). fatal: Could not read from remote repository. Please make sure you have the correct access rights and the…