成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

揭秘MySQL多版本并發(fā)控制實(shí)現(xiàn)原理

數(shù)據(jù)庫(kù) MySQL
MySQL 中多版本并發(fā)控制(MVCC),是現(xiàn)代數(shù)據(jù)庫(kù)引擎實(shí)現(xiàn)中常用的處理讀寫(xiě)沖突的手段,MVCC 作為 MySQL 高級(jí)應(yīng)用特性,目的在于提高數(shù)據(jù)庫(kù)高并發(fā)場(chǎng)景下的吞吐性能。

 MySQL 中多版本并發(fā)控制(MVCC),是現(xiàn)代數(shù)據(jù)庫(kù)引擎實(shí)現(xiàn)中常用的處理讀寫(xiě)沖突的手段,MVCC 作為 MySQL 高級(jí)應(yīng)用特性,目的在于提高數(shù)據(jù)庫(kù)高并發(fā)場(chǎng)景下的吞吐性能。

一、MVCC出現(xiàn)背景是什么?

事務(wù)的4個(gè)隔離級(jí)別以及對(duì)應(yīng)的3種異常:

  • 臟讀:一個(gè)事務(wù)讀取到了另外一個(gè)事務(wù)沒(méi)有提交的數(shù)據(jù);

  • 不可重復(fù)讀: 在同一事務(wù)中,兩次讀取同一數(shù)據(jù),得到內(nèi)容不同;

  • 幻讀: 同一事務(wù)中,用同樣的操作讀取兩次,得到的記錄數(shù)不相同。

在 MySQL 中, 默認(rèn)的隔離級(jí)別是可重復(fù)讀 ,可以解決臟讀和不可重復(fù)讀的問(wèn)題,但不能解決幻讀問(wèn)題。如果我們想要解決幻讀問(wèn)題,就需要采用串行化的方式,也就是將隔離級(jí)別提升到最高,但這樣一來(lái)就會(huì)大幅降低數(shù)據(jù)庫(kù)的事務(wù)并發(fā)能力。

而MVCC就是通過(guò)樂(lè)觀鎖的方式來(lái)解決不可重復(fù)讀和幻讀問(wèn)題,它可以在大多數(shù)情況下替代行級(jí)鎖,降低系統(tǒng)的開(kāi)銷。

MySQL 并發(fā)事務(wù)會(huì)引起更新丟失問(wèn)題,解決辦法是鎖,主要分兩類:

  • 樂(lè)觀鎖:

    其實(shí)現(xiàn)如同它的名字一樣,是假設(shè)比較好的情況。

    每次取數(shù)據(jù)的時(shí)候都認(rèn)為他人不會(huì)對(duì)其修改,所以不會(huì)上鎖,但是在更新的時(shí)候會(huì)判斷一下在此期間別人有沒(méi)有去更新這個(gè)數(shù)據(jù),可以使用版本號(hào)機(jī)制和CAS算法實(shí)現(xiàn)。

  • 悲觀鎖:

    悲觀鎖也如同它的名字一樣,總是假設(shè)比較壞的情況,每次取數(shù)據(jù)的時(shí)候都認(rèn)為他人會(huì)修改,所以每次在拿數(shù)據(jù)的時(shí)候都會(huì)上鎖,這樣別人想拿這個(gè)數(shù)據(jù)就會(huì)阻塞直到它拿到鎖(共享資源每次只給一個(gè)線程使用,其它線程阻塞,用完后再把資源轉(zhuǎn)讓給其它線程)。

二、什么是MVCC,它解決了什么問(wèn)題?

MVCC 是通過(guò)數(shù)據(jù)行的多個(gè)版本管理來(lái)實(shí)現(xiàn)數(shù)據(jù)庫(kù)的并發(fā)控制,簡(jiǎn)單來(lái)說(shuō)它的思想就是保存數(shù)據(jù)的歷史版本。

我們可以通過(guò)比較版本號(hào)決定數(shù)據(jù)是否顯示出來(lái)(具體的規(guī)則后面會(huì)介紹到),讀取數(shù)據(jù)的時(shí)候不需要加鎖也可以保證事務(wù)的隔離效果。

通過(guò) MVCC 我們可以解決以下幾個(gè)問(wèn)題:

(1)讀寫(xiě)之間阻塞的問(wèn)題,通過(guò) MVCC 可以讓讀寫(xiě)互相不阻塞,即讀不阻塞寫(xiě),寫(xiě)不阻塞讀,這樣就可以提升事務(wù)并發(fā)處理能力。

(2)降低了死鎖的概率。這是因?yàn)?MVCC 采用了樂(lè)觀鎖的方式,讀取數(shù)據(jù)時(shí)并不需要加鎖,對(duì)于寫(xiě)操作,也只鎖定必要的行。

(3)解決一致性讀的問(wèn)題。一致性讀也被稱為快照讀,當(dāng)我們查詢數(shù)據(jù)庫(kù)在某個(gè)時(shí)間點(diǎn)的快照時(shí),只能看到這個(gè)時(shí)間點(diǎn)之前事務(wù)提交更新的結(jié)果,而不能看到這個(gè)時(shí)間點(diǎn)之后事務(wù)提交的更新結(jié)果。

解釋一下可能難以理解的幾個(gè)詞匯:

  • 快照讀:

    讀取的是快照數(shù)據(jù),不加鎖的簡(jiǎn)單的SELECT都屬于快照讀(只是普通的讀操作)。

  • 當(dāng)前讀:

    當(dāng)前讀就是讀取最新數(shù)據(jù),而不是歷史版本的數(shù)據(jù)。

    加鎖的SELECT,或者對(duì)數(shù)據(jù)進(jìn)行增刪改都會(huì)進(jìn)行當(dāng)前讀(包括加鎖的讀取和DML操作)。

三、應(yīng)用舉例分析

為了更好地讓大家理解MVCC,我們用一個(gè)示例場(chǎng)景來(lái)說(shuō)明。

假設(shè)有個(gè)賬戶金額表 user_balance,包括三個(gè)字段,分別是 username 用戶名、balance 余額和 bankcard 卡號(hào),表數(shù)據(jù)如下所示:

用戶 A 和用戶 B 之間進(jìn)行轉(zhuǎn)賬,此時(shí)數(shù)據(jù)庫(kù)管理員想要查詢 user_balance 表中的總金額,兩個(gè)場(chǎng)景存在并發(fā)情況,在沒(méi)有MVCC的情況下,會(huì)出現(xiàn)哪些問(wèn)題呢。

Case1 :因?yàn)樾枰捎眉有墟i的方式,用戶 A 給 B 轉(zhuǎn)賬時(shí)間等待很久,如下圖所示。

Case2 :當(dāng)我們讀取的時(shí)候用了加行鎖,可能會(huì)出現(xiàn)死鎖的情況,如下圖所示。

比如當(dāng)我們讀到 A 有 1000 元的時(shí)候,此時(shí) B 開(kāi)始執(zhí)行給 A 轉(zhuǎn)賬。

四、InnoDB如何實(shí)現(xiàn)MVCC?

當(dāng)查詢一條記錄的時(shí)候,執(zhí)行流程如下:

  1. 首先獲取事務(wù)自己的版本號(hào),也就是事務(wù) ID;

  2. 獲取 Read View;

  3. 查詢得到的數(shù)據(jù),然后與 Read View 中的事務(wù)版本號(hào)進(jìn)行比較;

  4. 如果不符合 ReadView 規(guī)則,就需要從 Undo Log 中獲取歷史快照;

  5. 最后返回符合規(guī)則的數(shù)據(jù)。

相關(guān)概念

1. 事務(wù)版本號(hào)

一個(gè)自增長(zhǎng)的事務(wù)ID,用于標(biāo)記事務(wù)執(zhí)行的先后順序。

2. Read View

在 MVCC 機(jī)制中,多個(gè)事務(wù)對(duì)同一個(gè)行記錄進(jìn)行更新會(huì)產(chǎn)生多個(gè)歷史快照,這些歷史快照保存在 Undo Log 里。如果一個(gè)事務(wù)想要查詢這個(gè)行記錄,需要讀取哪個(gè)版本的行記錄呢?

這時(shí)就需要用到 Read View 了,它幫我們解決了行的可見(jiàn)性問(wèn)題。Read View 保存了當(dāng)前事務(wù)開(kāi)啟時(shí)所有活躍(還沒(méi)有提交)的事務(wù)列表,換個(gè)角度,可以理解為 Read View 保存了不應(yīng)該讓這個(gè)事務(wù)看到的其他的事務(wù) ID 列表。

Read VIew 中的幾個(gè)重要屬性:

  • up_limit_id,活躍的事務(wù)中最小的事務(wù) ID;

  • trx_ids,系統(tǒng)當(dāng)前正在活躍的事務(wù) ID 集合;

  • low_limit_id,活躍的事務(wù)中最大的事務(wù) ID;

  • creator_trx_id,創(chuàng)建這個(gè) Read View 的事務(wù) ID。

3. 行記錄的隱藏列

InnoDB 的葉子節(jié)點(diǎn)段存儲(chǔ)了數(shù)據(jù)頁(yè),數(shù)據(jù)頁(yè)中保存了行記錄,在這些行記錄中有一些重要的隱藏字段:

  • DB_ROW_ID :

    6-byte,記錄操作該數(shù)據(jù)事務(wù)的事務(wù)ID;

  • DB_TRX_ID :

    6-byte,當(dāng)創(chuàng)建表沒(méi)有合適的索引作為聚集索引時(shí),會(huì)用該隱藏ID創(chuàng)建聚集索引;

  • DB_ROLL_PTR :

    7-byte,回滾指針,指向上一個(gè)版本數(shù)據(jù)在undo log 里的位置指針;

4. 聚集索引

聚集索引是指數(shù)據(jù)庫(kù)表行中數(shù)據(jù)的物理順序與鍵值的邏輯(索引)順序相同。一個(gè)表只能有一個(gè)聚集索引,因?yàn)橐粋€(gè)表的物理順序只有一種情況,所以,對(duì)應(yīng)的聚集索引只能有一個(gè)。

5. Undo Log

InnoDB 將行記錄快照保存在 Undo Log,可以在回滾段中找到它們,主要用于記錄數(shù)據(jù)被修改之前的日志,在對(duì)表信息做修改之前先會(huì)把數(shù)據(jù)拷貝到Undo Log里,當(dāng)事務(wù)進(jìn)行回滾時(shí)可以通過(guò)Undo Log里的日志進(jìn)行數(shù)據(jù)還原。

回滾段中回滾指針間關(guān)聯(lián)關(guān)系,如下圖所示:

五、InnoDB是如何解決幻讀的?

1、在讀已提交的情況下,即使采用了 MVCC 方式也會(huì)出現(xiàn)幻讀

我們同時(shí)開(kāi)啟事務(wù) A 和事務(wù) B,先在事務(wù) A 中進(jìn)行某個(gè)條件范圍的查詢,讀取的時(shí)候采用排它鎖,在事務(wù) B 中增加一條符合該條件范圍的數(shù)據(jù),并進(jìn)行提交,然后我們?cè)谑聞?wù) A 中再次查詢?cè)摋l件范圍的數(shù)據(jù),就會(huì)發(fā)現(xiàn)結(jié)果集中多出一個(gè)符合條件的數(shù)據(jù),這樣就出現(xiàn)了幻讀。

出現(xiàn)幻讀的原因是在讀已提交的情況下,InnoDB 只采用記錄鎖(Record Locking)。

InnoDB 三種行鎖的方式:

  • 記錄鎖:

    針對(duì)單個(gè)行記錄添加鎖。

  • 間隙鎖(Gap Locking):

    可以鎖住一個(gè)范圍(索引之間的空隙),但不包括記錄本身。

    采用間隙鎖的方式可以防止幻讀情況的產(chǎn)生。

  • Next-Key 鎖:

    鎖住一個(gè)范圍,同時(shí)鎖定記錄本身,相當(dāng)于間隙鎖 + 記錄鎖,可以解決幻讀的問(wèn)題。

2、在可重復(fù)讀的情況下,InnoDB 可以通過(guò) Next-Key 鎖 +MVCC 來(lái)解決幻讀問(wèn)題。

想插入球員艾利克斯·倫(身高 2.16 米)的時(shí)候,事務(wù) B 會(huì)超時(shí),無(wú)法插入該數(shù)據(jù)。

這是因?yàn)椴捎昧?nbsp;Next-Key 鎖,會(huì)將 height>2.08 的范圍都進(jìn)行鎖定,就無(wú)法插入符合這個(gè)范圍的數(shù)據(jù)了。然后事務(wù) A 重新進(jìn)行條件范圍的查詢,就不會(huì)出現(xiàn)幻讀的情況。

六、總結(jié)

MVCC 的核心就是 Undo Log+ Read View。

  • “MV”就是通過(guò) Undo Log 來(lái)保存數(shù)據(jù)的歷史版本,實(shí)現(xiàn)多版本的管理;

  • “CC”是通過(guò) Read View 來(lái)實(shí)現(xiàn)管理,通過(guò) Read View 原則來(lái)決定數(shù)據(jù)是否顯示。

同時(shí)針對(duì)不同的隔離級(jí)別,Read View 的生成策略不同,也就實(shí)現(xiàn)了不同的隔離級(jí)別。

 

責(zé)任編輯:張燕妮 來(lái)源: 架構(gòu)精進(jìn)之路
相關(guān)推薦

2018-08-20 16:00:23

MySQL并發(fā)控制MVCC

2011-08-17 10:11:34

MySQL數(shù)據(jù)庫(kù)MVCC

2025-05-19 08:05:00

數(shù)據(jù)庫(kù)MVCCMySQL

2009-11-16 09:05:47

PostgreSQLInnoDB多版本并發(fā)控制

2017-08-21 10:56:55

MySQL并發(fā)控制

2023-12-06 08:23:16

MVCCmysql

2019-07-24 11:30:54

程序員技能開(kāi)發(fā)者

2021-08-02 09:01:05

MySQL 多版本并發(fā)數(shù)據(jù)庫(kù)

2020-09-22 08:52:50

平臺(tái)實(shí)現(xiàn)消息

2021-04-07 06:00:18

JavaScript 前端并發(fā)控制

2021-01-12 10:22:45

JavaScript并發(fā)控制前端

2024-10-10 17:46:06

2025-06-12 05:00:00

@Autowired自動(dòng)裝配實(shí)現(xiàn)機(jī)制

2022-04-08 08:32:40

mobx狀態(tài)管理庫(kù)redux

2009-02-09 10:06:03

并發(fā)控制Web應(yīng)用悲觀鎖

2020-02-25 16:48:35

AndroidGoogle 移動(dòng)系統(tǒng)

2021-05-13 23:30:17

JavaScript 原理揭秘

2025-03-20 06:48:55

性能優(yōu)化JDK

2022-11-18 18:36:24

2025-01-03 09:36:22

Nginx高并發(fā)進(jìn)程
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 国产精品1区2区 | 一区二区三区国产在线观看 | www.色.com| 久久国产成人午夜av影院武则天 | 夜夜骑首页| 亚洲国产一 | 免费的色网站 | 黄色免费在线观看 | 久久亚洲综合 | 天天狠狠 | 中文二区 | 天天综合日日夜夜 | 国产亚洲精品综合一区 | 久久在线视频 | 久久精品国产久精国产 | 欧美精 | www成人免费视频 | 久久久久久久av | av电影一区二区 | 伊人超碰 | 欧美日韩中文国产一区发布 | 亚洲成人高清 | 国产精品久久久久久久久久久久久 | 91在线网 | 久久久一区二区三区 | 日本粉嫩一区二区三区视频 | 国产精品一区在线播放 | 国产精品福利视频 | 国产人免费人成免费视频 | 九九精品久久久 | 午夜在线小视频 | 综合视频在线 | 天天操天天干天天透 | 中文字幕在线免费视频 | 成人福利 | 国产精品成av人在线视午夜片 | 中文字幕精品一区二区三区精品 | 91免费电影 | 国产精品中文 | 精品videossex高潮汇编 | 日韩精品视频在线 |