最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

MySQL?MVCC(多版本并發(fā)控制)實(shí)現(xiàn)機(jī)制詳細(xì)講解

 更新時(shí)間:2026年06月09日 10:27:21   作者:xiaolyuh123  
MVCC是一種用于管理數(shù)據(jù)庫(kù)并發(fā)訪問(wèn)的技術(shù),它通過(guò)在數(shù)據(jù)庫(kù)中存儲(chǔ)數(shù)據(jù)的多個(gè)版本來(lái)避免讀寫沖突,從而提高了數(shù)據(jù)庫(kù)的并發(fā)性能,這篇文章主要介紹了MySQL?MVCC(多版本并發(fā)控制)實(shí)現(xiàn)的相關(guān)資料,需要的朋友可以參考下

前言

MVCC(Multi-Version Concurrency Control,多版本并發(fā)控制)是InnoDB存儲(chǔ)引擎解決讀寫沖突、提升并發(fā)性能的核心技術(shù)——它通過(guò)為數(shù)據(jù)行維護(hù)多個(gè)版本(快照),讓讀操作(SELECT)無(wú)需加鎖即可讀取數(shù)據(jù),實(shí)現(xiàn)讀不阻塞寫、寫不阻塞讀的高并發(fā)效果。

一、MVCC核心概念

1.1 什么是MVCC

MVCC是InnoDB專為讀已提交(RC)可重復(fù)讀(RR) 隔離級(jí)別設(shè)計(jì)的并發(fā)控制機(jī)制,核心特征如下:

  • 核心思想:為每一行數(shù)據(jù)維護(hù)多個(gè)版本(快照),不同事務(wù)讀取時(shí),根據(jù)規(guī)則選擇對(duì)應(yīng)版本的數(shù)據(jù),而非直接讀取最新數(shù)據(jù);
  • 適用場(chǎng)景:僅針對(duì)快照讀(普通SELECT 生效,當(dāng)前讀(SELECT ```FOR UPDATE/LOCK IN SHARE MODE、INSERT/UPDATE/DELETE)仍需加鎖;
  • 目標(biāo):解決“讀寫沖突”,避免傳統(tǒng)鎖機(jī)制中“讀阻塞寫、寫阻塞讀”的問(wèn)題,提升并發(fā)性能。

1.2 MVCC的核心目標(biāo)

  • 讀操作無(wú)鎖化:快照讀無(wú)需加行鎖/表鎖,不阻塞寫操作;
  • 數(shù)據(jù)一致性:保證不同事務(wù)在各自隔離級(jí)別下,讀取到符合規(guī)則的一致數(shù)據(jù);
  • 歷史版本可回溯:通過(guò)版本鏈,支持事務(wù)讀取“過(guò)去某個(gè)時(shí)間點(diǎn)”的數(shù)據(jù)(如RR隔離級(jí)別的可重復(fù)讀)。

二、MVCC實(shí)現(xiàn)的三大基礎(chǔ)組件

InnoDB的MVCC依賴行記錄隱藏字段、Undo Log(回滾日志)Read View(讀視圖) 三大核心組件,三者協(xié)同完成多版本數(shù)據(jù)的管理和讀取。

2.1 行記錄的隱藏字段

InnoDB為每一行數(shù)據(jù)(除自定義字段外)自動(dòng)添加3個(gè)隱藏字段,是MVCC的基礎(chǔ):

隱藏字段字段類型核心作用
DB_TRX_ID6字節(jié)記錄最后一次插入/更新該行數(shù)據(jù)的事務(wù)ID(刪除視為特殊的更新,標(biāo)記刪除);
DB_ROLL_PTR7字節(jié)回滾指針,指向該行數(shù)據(jù)的Undo Log版本鏈(通過(guò)該指針可回溯歷史版本);
DB_ROW_ID6字節(jié)聚簇索引無(wú)主鍵/唯一鍵時(shí),InnoDB自動(dòng)生成的行ID(僅用于標(biāo)識(shí)行,非MVCC核心);

示例

假設(shè)有表user(id INT PRIMARY KEY, name VARCHAR(20)),插入一行(1, '張三'),該行的實(shí)際存儲(chǔ)結(jié)構(gòu)為:

idnameDB_TRX_IDDB_ROLL_PTRDB_ROW_ID
1張三100指向Undo LogNULL

(注:DB_TRX_ID=100表示插入該記錄的事務(wù)ID為100)

2.2 Undo Log(回滾日志)

Undo Log是InnoDB在修改數(shù)據(jù)時(shí),記錄的“數(shù)據(jù)修改前的快照”,是實(shí)現(xiàn)版本鏈的核心載體。

2.2.1 Undo Log的類型

  • Insert Undo Log:僅記錄INSERT操作的日志,事務(wù)提交后可直接刪除(因INSERT的記錄僅當(dāng)前事務(wù)可見(jiàn),無(wú)版本回溯需求);
  • Update Undo Log:記錄UPDATE/DELETE操作的日志,事務(wù)提交后需保留(供其他事務(wù)的MVCC讀取歷史版本),直到?jīng)]有事務(wù)需要訪問(wèn)該版本時(shí),由Purge線程清理。

2.2.2 版本鏈(Version Chain)

每次更新行數(shù)據(jù)時(shí),InnoDB會(huì)按以下步驟維護(hù)版本鏈:

  1. 將更新前的數(shù)據(jù)寫入Update Undo Log
  2. 更新行記錄的DB_TRX_ID為當(dāng)前事務(wù)ID;
  3. 更新行記錄的DB_ROLL_PTR,指向剛生成的Update Undo Log;
  4. 多次更新后,DB_ROLL_PTR會(huì)串聯(lián)所有歷史版本,形成版本鏈(鏈頭是最新版本,鏈尾是最早版本)。

版本鏈?zhǔn)纠?/strong>:

當(dāng)前行版本(DB_TRX_ID=102) → DB_ROLL_PTR → 版本1(DB_TRX_ID=101) → DB_ROLL_PTR → 版本0(DB_TRX_ID=100)

2.3 Read View(讀視圖)

Read View是事務(wù)執(zhí)行快照讀時(shí),生成的一個(gè)“可見(jiàn)性判斷規(guī)則”,核心作用是:判斷當(dāng)前事務(wù)能看到哪些版本的數(shù)據(jù)。

2.3.1 Read View的核心字段

Read View包含4個(gè)關(guān)鍵字段,用于版本可見(jiàn)性判斷:

字段名含義
m_ids生成Read View時(shí),當(dāng)前活躍的事務(wù)ID集合(未提交的事務(wù)ID);
min_trx_idm_ids中的最小事務(wù)ID(活躍事務(wù)的最小ID);
max_trx_id系統(tǒng)下一個(gè)要分配的事務(wù)ID(大于當(dāng)前所有已分配的事務(wù)ID);
creator_trx_id創(chuàng)建該Read View的事務(wù)ID(當(dāng)前執(zhí)行快照讀的事務(wù)ID);

2.3.2 版本可見(jiàn)性判斷規(guī)則

事務(wù)讀取行數(shù)據(jù)時(shí),通過(guò)Read View判斷該行的某個(gè)版本是否可見(jiàn):
假設(shè)待判斷版本的DB_TRX_ID = trx_id,規(guī)則如下:

  1. trx_id < min_trx_id:該版本由“已提交的事務(wù)”生成,可見(jiàn)
  2. trx_id >= max_trx_id:該版本由“未來(lái)的事務(wù)”生成(當(dāng)前事務(wù)未開(kāi)始時(shí),該事務(wù)還未創(chuàng)建),不可見(jiàn);
  3. min_trx_id ≤ trx_id < max_trx_id
    • trx_id ∈ m_ids:該版本由“當(dāng)前活躍的未提交事務(wù)”生成,不可見(jiàn);
    • trx_id ∉ m_ids:該版本由“已提交的事務(wù)”生成,可見(jiàn);
  4. 若版本不可見(jiàn),則通過(guò)DB_ROLL_PTR回溯版本鏈,直到找到第一個(gè)可見(jiàn)的版本(或無(wú)可見(jiàn)版本)。

三、MVCC核心執(zhí)行邏輯(以RR隔離級(jí)別為例)

以MySQL默認(rèn)的可重復(fù)讀(RR) 隔離級(jí)別為例,拆解MVCC在INSERT/UPDATE/DELETE/SELECT中的執(zhí)行流程。

3.1 數(shù)據(jù)插入(INSERT)

  1. 事務(wù)T1(ID=100)執(zhí)行INSERT INTO user(id, name) VALUES (1, '張三');
  2. InnoDB為該行數(shù)據(jù)寫入DB_TRX_ID=100,DB_ROLL_PTR=NULL(無(wú)歷史版本);
  3. 生成Insert Undo Log(僅用于事務(wù)回滾,提交后刪除);
  4. 事務(wù)提交后,該行數(shù)據(jù)的版本僅對(duì)已提交的事務(wù)可見(jiàn)。

3.2 數(shù)據(jù)更新(UPDATE)

  1. 事務(wù)T2(ID=101)執(zhí)行UPDATE user SET name='李四' WHERE id=1
  2. InnoDB先將該行當(dāng)前版本(DB_TRX_ID=100)寫入Update Undo Log;
  3. 更新行記錄的DB_TRX_ID=101,DB_ROLL_PTR指向剛生成的Update Undo Log;
  4. 此時(shí)版本鏈:當(dāng)前版本(101)→ 歷史版本(100);
  5. 事務(wù)提交后,Update Undo Log保留,供其他事務(wù)讀取歷史版本。

3.3 數(shù)據(jù)刪除(DELETE)

DELETE被InnoDB視為“特殊的UPDATE”,執(zhí)行流程如下:

  1. 事務(wù)T3(ID=102)執(zhí)行DELETE FROM user WHERE id=1
  2. InnoDB將該行當(dāng)前版本寫入Update Undo Log;
  3. 更新行記錄的DB_TRX_ID=102,并標(biāo)記“刪除標(biāo)識(shí)”(物理刪除由Purge線程異步完成);
  4. 版本鏈新增一條:當(dāng)前版本(102,標(biāo)記刪除)→ 版本1(101)→ 版本0(100)。

3.4 數(shù)據(jù)讀?。⊿ELECT,快照讀)

假設(shè)當(dāng)前有活躍事務(wù)ID:101、102,事務(wù)T4(ID=103)執(zhí)行SELECT * FROM user WHERE id=1(RR隔離級(jí)別):

  1. T4第一次執(zhí)行SELECT時(shí),生成Read View:
    • m_ids = {101, 102},min_trx_id=101,max_trx_id=104creator_trx_id=103;
  2. 讀取行數(shù)據(jù)的當(dāng)前版本(DB_TRX_ID=102),判斷可見(jiàn)性:
    • 102 ≥ min_trx_id(101)102 < max_trx_id(104),且102 ∈ m_ids → 不可見(jiàn);
  3. 通過(guò)DB_ROLL_PTR回溯版本鏈,讀取上一個(gè)版本(DB_TRX_ID=101):
    • 101 ∈ m_ids → 不可見(jiàn);
  4. 繼續(xù)回溯到版本0(DB_TRX_ID=100):
    • 100 < min_trx_id(101) → 可見(jiàn);
  5. 返回該版本的數(shù)據(jù)(name='張三');
  6. RR隔離級(jí)別下,T4后續(xù)的SELECT會(huì)復(fù)用該Read View,因此多次讀取結(jié)果一致(可重復(fù)讀)。

四、不同隔離級(jí)別下的MVCC行為

MVCC僅在讀已提交(RC)可重復(fù)讀(RR) 隔離級(jí)別生效,核心區(qū)別是Read View的創(chuàng)建時(shí)機(jī)

隔離級(jí)別Read View創(chuàng)建時(shí)機(jī)讀取結(jié)果特點(diǎn)
讀已提交(RC)每次執(zhí)行快照讀(SELECT)時(shí),重新創(chuàng)建Read View同一事務(wù)內(nèi)多次SELECT可能讀取到不同版本(不可重復(fù)讀),僅能看到已提交的最新版本;
可重復(fù)讀(RR)事務(wù)內(nèi)第一次執(zhí)行快照讀時(shí)創(chuàng)建Read View,后續(xù)復(fù)用同一事務(wù)內(nèi)多次SELECT讀取結(jié)果一致(可重復(fù)讀),僅能看到事務(wù)啟動(dòng)時(shí)已提交的版本;
讀未提交(RU)不使用MVCC,直接讀取最新數(shù)據(jù)(無(wú)版本控制)能看到未提交事務(wù)的數(shù)據(jù),存在臟讀;
串行化(SERIALIZABLE)禁用MVCC,所有讀操作加表鎖完全串行執(zhí)行,無(wú)并發(fā)沖突,但性能極低;

五、MVCC的優(yōu)勢(shì)與局限

5.1 優(yōu)勢(shì)

  • 高并發(fā):快照讀無(wú)鎖,讀寫互不阻塞,大幅提升并發(fā)性能;
  • 數(shù)據(jù)一致性:在RC/RR隔離級(jí)別下,保證讀取數(shù)據(jù)的一致性,避免臟讀(RC/RR)、不可重復(fù)讀(RR);
  • 無(wú)鎖讀:無(wú)需加行鎖/表鎖,減少鎖競(jìng)爭(zhēng)和死鎖概率。

5.2 局限

  • 版本鏈開(kāi)銷:大量更新操作會(huì)導(dǎo)致版本鏈過(guò)長(zhǎng),增加讀取時(shí)的回溯成本;
  • Undo Log清理:Purge線程需異步清理過(guò)期的Undo Log,若清理不及時(shí)會(huì)占用磁盤空間;
  • 僅適用于快照讀:當(dāng)前讀(如SELECT ```FOR UPDATE)仍需加鎖,無(wú)法避免寫沖突。

總結(jié)

  1. 核心依賴:MVCC基于行記錄隱藏字段(DB_TRX_ID/DB_ROLL_PTR)、Undo Log版本鏈、Read View可見(jiàn)性規(guī)則實(shí)現(xiàn);
  2. 核心邏輯:更新數(shù)據(jù)時(shí)生成版本鏈,讀取數(shù)據(jù)時(shí)通過(guò)Read View判斷版本可見(jiàn)性,回溯版本鏈找到符合規(guī)則的版本;
  3. 隔離級(jí)別差異:RC每次SELECT創(chuàng)建Read View(不可重復(fù)讀),RR僅第一次創(chuàng)建(可重復(fù)讀);
  4. 核心價(jià)值:實(shí)現(xiàn)“讀不阻塞寫、寫不阻塞讀”,是InnoDB高并發(fā)的核心保障。

到此這篇關(guān)于MySQL MVCC(多版本并發(fā)控制)實(shí)現(xiàn)機(jī)制的文章就介紹到這了,更多相關(guān)MySQL MVCC多版本并發(fā)控制內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • DBeaver導(dǎo)入.sql后綴文件詳細(xì)圖文教程

    DBeaver導(dǎo)入.sql后綴文件詳細(xì)圖文教程

    DBeaver是一款數(shù)據(jù)庫(kù)管理工具,最重要的是他是一款比較好的開(kāi)源工具,這篇文章主要介紹了DBeaver導(dǎo)入.sql后綴文件的相關(guān)資料,文中通過(guò)圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2025-12-12
  • MySQL學(xué)習(xí)之索引及優(yōu)化

    MySQL學(xué)習(xí)之索引及優(yōu)化

    這篇文章主要介紹MySQL的索引及優(yōu)化,索引是幫助MySQL進(jìn)行高效查詢的一種數(shù)據(jù)結(jié)構(gòu)。好比一本書的目錄,能加快查詢的速度,想進(jìn)一步了解的小伙伴可以詳細(xì)閱讀本文
    2023-03-03
  • mysql數(shù)據(jù)庫(kù)id主鍵自增加刪除后不連續(xù)如何解決

    mysql數(shù)據(jù)庫(kù)id主鍵自增加刪除后不連續(xù)如何解決

    這篇文章主要介紹了mysql數(shù)據(jù)庫(kù)id主鍵自增加刪除后不連續(xù)的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • windows10安裝mysql5.7.17教程

    windows10安裝mysql5.7.17教程

    windows10安裝mysql5.7.17是這樣安裝的嗎?這篇文章主要為大家詳細(xì)介紹了win10下mysql5.7.17安裝配置方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-01-01
  • 詳解mysql數(shù)據(jù)庫(kù)中文亂碼問(wèn)題

    詳解mysql數(shù)據(jù)庫(kù)中文亂碼問(wèn)題

    這篇文章主要介紹了詳解mysql數(shù)據(jù)庫(kù)中文亂碼問(wèn)題的相關(guān)資料,需要的朋友可以參考下
    2017-10-10
  • 分組查詢GROUP BY的使用與SQL執(zhí)行順序的講解

    分組查詢GROUP BY的使用與SQL執(zhí)行順序的講解

    今天小編就為大家分享一篇關(guān)于分組查詢GROUP BY的使用與SQL執(zhí)行順序的講解,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2019-03-03
  • MySQL表的CURD操作(數(shù)據(jù)的增刪改查)

    MySQL表的CURD操作(數(shù)據(jù)的增刪改查)

    數(shù)據(jù)庫(kù)本質(zhì)上是一個(gè)文件系統(tǒng),通過(guò)標(biāo)準(zhǔn)的SQL語(yǔ)句對(duì)數(shù)據(jù)進(jìn)行CURD操作,下面這篇文章主要給大家介紹了關(guān)于MySQL表的CURD操作的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-02-02
  • MySQL實(shí)現(xiàn)數(shù)據(jù)更新的示例詳解

    MySQL實(shí)現(xiàn)數(shù)據(jù)更新的示例詳解

    這篇文章主要為大家詳細(xì)介紹了MySQL實(shí)現(xiàn)數(shù)據(jù)更新的相關(guān)資料,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • Mysql 索引從入門到精通(從原理到實(shí)踐)

    Mysql 索引從入門到精通(從原理到實(shí)踐)

    本文介紹MySQL索引深度解析:從原理到實(shí)踐,本文涵蓋索引基礎(chǔ)概念、類型、底層原理及管理策略,結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧
    2025-10-10
  • MySQL四種備份表的實(shí)現(xiàn)方式

    MySQL四種備份表的實(shí)現(xiàn)方式

    本文主要介紹了MySQL四種備份表的實(shí)現(xiàn)方式,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2024-02-02

最新評(píng)論

永春县| 陇川县| 建昌县| 岑溪市| 阜城县| 安阳市| 墨玉县| 乌苏市| 长兴县| 梨树县| 新河县| 治多县| 九寨沟县| 南木林县| 霍邱县| 怀柔区| 沁水县| 高淳县| 洛浦县| 博罗县| 通城县| 钟祥市| 铜鼓县| 威宁| 娱乐| 和政县| 巴楚县| 宣城市| 乌鲁木齐市| 杭州市| 安岳县| 福清市| 开阳县| 丰原市| 石渠县| 东平县| 成安县| 庆元县| 吴堡县| 佛山市| 孝义市|