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

Mysql InnoDB多版本并發(fā)控制MVCC詳解

 更新時(shí)間:2022年11月29日 08:33:15   作者:Cuzzz  
這篇文章主要介紹了Mysql InnoDB多版本并發(fā)控制MVCC詳解的相關(guān)資料,需要的朋友可以參考下

一丶為什么需要事務(wù)隔離級(jí)別

mysql是一個(gè)客戶端/服務(wù)端軟件,對(duì)于同一個(gè)服務(wù)器來說,可以有多個(gè)客戶端進(jìn)行連接,每一個(gè)客戶端進(jìn)行連接之后就形成一個(gè)會(huì)話,每一個(gè)客戶端都可以在自己的會(huì)話中向服務(wù)器發(fā)出請(qǐng)求語句,一個(gè)請(qǐng)求語句可能是某一個(gè)事務(wù)的一部分,服務(wù)器可以同時(shí)處理多個(gè)事務(wù)。

如果事務(wù)時(shí)一個(gè)接著一個(gè)進(jìn)行,那么下一個(gè)事務(wù)是在上一個(gè)事務(wù)的一致性前提下進(jìn)行的,就沒用一致性的問題,但是事務(wù)是并發(fā)進(jìn)行且可能訪問到相同的數(shù)據(jù)這時(shí)候就會(huì)出現(xiàn)如下問題

可以看到AB最開始總和13元,最后AB總和18元,銀行血虧五元,這顯然違背了一致性——錢的總量不變。這就是并發(fā)情況下兩個(gè)事務(wù)的影響,所以需要事務(wù)隔離讓事務(wù)隔離的進(jìn)行,互不干涉。

1.實(shí)現(xiàn)事務(wù)隔離的方式:串行執(zhí)行

最簡(jiǎn)單直接的方式,同一時(shí)間只能有一個(gè)事務(wù)運(yùn)行,這樣必然不會(huì)有上述不一致的情況,但是大大降低了吞吐率并增加了事務(wù)的等待時(shí)間

2.實(shí)現(xiàn)事務(wù)隔離的方式:可串行執(zhí)行

并發(fā)事務(wù)之所以出現(xiàn)不一致的情況,就是由于多個(gè)事務(wù)訪問相同的數(shù)據(jù),需要實(shí)現(xiàn)多個(gè)事務(wù)在訪問相同數(shù)據(jù)的時(shí)候進(jìn)行限制,比方說上圖中事務(wù)2想訪問A賬戶的值需要等待事務(wù)提交事務(wù)之后,這樣可以讓并發(fā)事務(wù)的執(zhí)行如同串行執(zhí)行的效果一樣。

二丶并發(fā)事務(wù)執(zhí)行的問題:臟寫,臟讀,不可重復(fù)讀,幻讀

1.臟寫

一個(gè)事務(wù)修改了另外一個(gè)未提交事務(wù)修改過的數(shù)據(jù)

臟寫導(dǎo)致一致性無法保證

上圖事務(wù)A和事務(wù)B都更新紫色數(shù)據(jù),其中事務(wù)A首先更新為A,然后事務(wù)B過來更新為B,這時(shí)候事務(wù)A回滾后更新為Null,事務(wù) B 明明正常寫了一行數(shù)據(jù),但是寫完之后發(fā)現(xiàn)值變了,有點(diǎn)丟失更新的意思。(比如A表示余額,這時(shí)候在將余額A判斷是否足以支付,判斷得到可以,事務(wù)B執(zhí)行扣費(fèi)寫入A-5,商家收到5元,結(jié)果這時(shí)候回滾了,A變成Null,事務(wù)A中轉(zhuǎn)錢的一方錢變?yōu)锳,錢的總額變?yōu)锳+5了)

臟寫導(dǎo)致原子性受到破壞

假如上述的事務(wù)B還操作了另外的數(shù)據(jù),比如插入一條數(shù)據(jù)C,并且更改為B寫入C是在一個(gè)事務(wù)下面的,需要具備原子性,但是臟寫讓B的更改需要部分回滾為Null,這樣插入C和更改B就不具備原子性(比如A表示余額,這時(shí)候在將余額A判斷是否足以支付,判斷得到可以,事務(wù)B執(zhí)行扣費(fèi)寫入A-5,商家收到5元,結(jié)果這時(shí)候回滾了,A變成Null,這時(shí)候部分回滾,商家的5元沒用回滾,商家的庫存也沒用回滾,原子性被破壞)

2.臟讀

如果一個(gè)事務(wù)讀取到另外一個(gè)事務(wù)未提交的數(shù)據(jù),意味著發(fā)生了臟讀

比如事務(wù)A先寫數(shù)據(jù)A,然后事務(wù)B督導(dǎo)數(shù)據(jù)A后在內(nèi)存中使用A進(jìn)行一系列操作(比如A表示余額,這時(shí)候在將余額A判斷是否足以支付,判斷得到可以)但是事務(wù)A這時(shí)候回滾了,事務(wù)B再次讀取數(shù)據(jù)發(fā)現(xiàn)為null,這就是臟讀。

臟讀可能引發(fā)一致性的問題:比如事務(wù)操作時(shí)修改x和y的值,并且二者總是相等的,A修改x為1,還沒來得及修改y也沒用提交事務(wù),這時(shí)候事務(wù)B讀取x=1,y=0,二者不等,事務(wù)B讀取到了數(shù)據(jù)庫不一致的狀態(tài),讀取到未提交事務(wù)的值

3.不可重復(fù)讀

假如一個(gè)事務(wù)修改了另外一個(gè)事務(wù)未提交的數(shù)據(jù),意味發(fā)生了不可重復(fù)讀

比如事務(wù)A第一次讀取到值為A,接著事務(wù)B修改為B,并且提交了事務(wù)B,然后事務(wù)A再次讀取得到的數(shù)據(jù)是B,同一行數(shù)據(jù)多次讀取值并不相同,這稱作不可重復(fù)讀。它是指在同一個(gè)事務(wù)里面查詢同一行數(shù)據(jù),每次查到的數(shù)據(jù)都不一樣。和臟讀區(qū)別在于臟讀是由于別的事務(wù)回滾導(dǎo)致,而不可重復(fù)讀讀到的其實(shí)是已經(jīng)提交的數(shù)據(jù)。

事務(wù)A讀到事務(wù)B提交后的數(shù)據(jù)似乎很合理,但是我們想象這樣一種場(chǎng)景:你有一個(gè)流水表和用戶余額,其中記錄用戶每天的流水,你在月初0點(diǎn)的時(shí)候核對(duì)流水和庫存,但是流水很多,你的程序選擇一個(gè)一個(gè)用戶的進(jìn)行核對(duì),核對(duì)用戶甲,甲沒做任何消費(fèi),但是當(dāng)你核對(duì)B的時(shí)候,你將B的流水load到內(nèi)存中,但是B這時(shí)候(0點(diǎn)30分,這一筆數(shù)據(jù)新的一個(gè)余額)進(jìn)行了扣除余額的操作,導(dǎo)致B余額和流水對(duì)不上了。

4.幻讀

如果一個(gè)事務(wù)A先根據(jù)沒用搜索條件查詢到一些記錄,在該事務(wù)未提交前,另外一個(gè)事務(wù)寫入(delete,update,insert)了符合搜索條件的記錄,這時(shí)候事務(wù)A再次讀取,發(fā)現(xiàn)數(shù)據(jù)條數(shù)和第一次讀取的不同,如同出現(xiàn)了幻覺,稱之為幻讀

事務(wù)A讀到事務(wù)B提交后的數(shù)據(jù)似乎很合理,但是我們想象這樣一種場(chǎng)景:你有一個(gè)需求將會(huì)公司的男性員工了女性員工查詢進(jìn)行展示,你先查詢了總數(shù)為100人,然后查詢男性的總數(shù)50人,后查詢女性人數(shù)準(zhǔn)備在頁面展示共100人,其中男50人,女50人,結(jié)果這是管理信息的人發(fā)現(xiàn)有一位員工性別錯(cuò)誤錄入了,將其從男修改為女,這時(shí)候你讀取事務(wù)就是女51人了,你在主頁顯示了共100人,其中男50人,女51人

三丶隔離級(jí)別

1.Read UnCommitted 讀未提交

在此隔離級(jí)別下,會(huì)發(fā)生臟讀,不可重復(fù)讀,和幻讀

2.Read Committed 讀已提交

在此隔離級(jí)別下,會(huì)發(fā)生不可重復(fù)讀,和幻讀

3.Repeatable Read 可重復(fù)讀

在此隔離級(jí)別下,可能發(fā)生幻讀

4.Serializable 可串行化

在此隔離級(jí)別下,不會(huì)發(fā)生臟讀,不可重復(fù)讀,和幻讀

其中臟寫是對(duì)一致性影響最嚴(yán)重的,無論是何種隔離級(jí)別,都不允許臟寫發(fā)生,innodb使用鎖保證不會(huì)出現(xiàn)臟寫現(xiàn)象,第一個(gè)事務(wù)更新某條記錄的時(shí)候,會(huì)給這條記錄加鎖,另外一個(gè)事務(wù)在此更新的時(shí)候,需要等待第一個(gè)事務(wù)提交釋放鎖后更新。隔離級(jí)別越高,其并發(fā)能力越低。

四丶Mysql設(shè)置隔離級(jí)別

默認(rèn)隔離級(jí)別可重復(fù)讀

1.設(shè)置全局隔離級(jí)別

SET GLOBAL TRANSACTION ISOLATION LEVEL 期望的隔離級(jí)別(可選READ UNCOMMITED,READ COMMITED,REPEATABLE READ,SERIALIZABLE),此命令只對(duì)執(zhí)行語句后新產(chǎn)生的會(huì)話有效,對(duì)當(dāng)前已經(jīng)存在的會(huì)話無效

2.設(shè)置會(huì)話隔離級(jí)別

SET SESSION TRANSACTION ISOLATION LEVEL 期望的隔離級(jí)別(可選READ UNCOMMITED,READ COMMITED,REPEATABLE READ,SERIALIZABLE),對(duì)當(dāng)前會(huì)話后續(xù)事務(wù)有效,該語句可以在已開啟的事務(wù)中執(zhí)行,但是不會(huì)影響當(dāng)前正在執(zhí)行的事務(wù),如果在事務(wù)之間執(zhí)行,只會(huì)對(duì)后續(xù)的事務(wù)有效

3.設(shè)置下一個(gè)事務(wù)的隔離級(jí)別

SET TRANSACTION ISOLATION LEVEL 期望的隔離級(jí)別(可選READ UNCOMMITED,READ COMMITED,REPEATABLE READ,SERIALIZABLE) 只對(duì)當(dāng)前會(huì)話的下一個(gè)即將開啟的事務(wù)有效,下一個(gè)事務(wù)執(zhí)行完后,后續(xù)事務(wù)將恢復(fù)到之前的隔離級(jí)別,該語句不能再已經(jīng)開啟的事務(wù)中執(zhí)行,否則會(huì)報(bào)錯(cuò)。

4.指定服務(wù)器的隔離級(jí)別

在啟動(dòng)的時(shí)候使用--transaction-isolation=xxx即可執(zhí)行默認(rèn)隔離級(jí)別

五丶MVCC原理

下面討論記錄對(duì)當(dāng)前事務(wù)是否可見都是基于當(dāng)前事務(wù)中執(zhí)行的查詢是快照讀(普通查詢),對(duì)于當(dāng)前讀(select xxx for update,select xxx lock in share mode)是不通用的

1.版本鏈

對(duì)于InnoDB存儲(chǔ)引擎來說,其聚簇索引記錄中包含兩個(gè)隱藏列:

trx_id:一個(gè)事務(wù)每次對(duì)聚簇索引記錄做出改動(dòng)的時(shí)候,都會(huì)把該事務(wù)的事務(wù)id復(fù)制給此列 roll_point:每次對(duì)某條聚簇索引記錄進(jìn)行改動(dòng)的時(shí),都會(huì)把舊的版本寫入到undo 日志中,此列相當(dāng)于一個(gè)指針,指向修改前的信息

每次修改都會(huì)形成Undo 日志,所有版本的數(shù)據(jù)會(huì)通過roll_point串聯(lián)成一個(gè)鏈表,稱之為版本鏈,頭節(jié)點(diǎn)是當(dāng)前記錄的最新值。利用版本鏈控制多個(gè)并發(fā)事務(wù)訪問相同記錄時(shí)的行為稱為MVCC多版本并發(fā)控制。

其實(shí)在undo日志中,只記錄被更新列的信息,而不是記錄全部的信息,對(duì)于沒有記錄的列,會(huì)通過版本鏈找少一個(gè)版本中的對(duì)應(yīng)列的信息,直到找到聚簇索引葉子節(jié)點(diǎn)中的內(nèi)容

2.Read View

對(duì)于使用Read Uncommitted隔離級(jí)別的事務(wù),可以讀取到?jīng)]提交的數(shù)據(jù),那么直接讀取最新的版本即可。對(duì)于Serializable隔離級(jí)別,innodb直接通過加鎖來訪問記錄。對(duì)于read committed 和 repeatable read隔離級(jí)別的事務(wù),都必須保證督導(dǎo)的數(shù)據(jù)是已經(jīng)提交事務(wù)修改過的記錄,那么如何判斷版本鏈中的哪個(gè)版本的數(shù)據(jù)是當(dāng)前事務(wù)可見的昵?

innodb 使用的Read View

2.1 read view 的結(jié)構(gòu)

  • m_ids:在生成read view時(shí),當(dāng)前系統(tǒng)中活躍的讀寫事務(wù)id列表
  • min_trx_id:生成read view時(shí),當(dāng)前系統(tǒng)中活躍的讀寫事務(wù)中最小事務(wù)id,也就是m_ids中的最小值
  • max_trx_id:生成read view時(shí),系統(tǒng)應(yīng)該分配給下一個(gè)事務(wù)的事務(wù)id值
  • creator_trx_id:生成該read view的事務(wù)的事務(wù)id

2.2 read view

  • 如果被訪問版本的trx_idcreator_trx_id相同,意味著當(dāng)前事務(wù)在訪問自己修改的記錄,自然可見
  • 如果訪問版本的trx_id屬性值小于read view中的min_trx_id 表明此版本是生成read view之前已經(jīng)提交的事務(wù),那么自然可見
  • 如果訪問版本的trx_id,大于等于read view中的max_trx_id說明,當(dāng)前版本數(shù)據(jù)是生成read view后開啟事務(wù)產(chǎn)生的,那么自然不可見
  • 如果訪問版本的trx_id 介于min_trx_idmax_trx_id之間,需要判斷trx_id是否位于m_ids列表中,如果在說明創(chuàng)建read view時(shí)生成該版本的事務(wù)還是活躍的,那么該版本,不可被訪問,如果不在說明創(chuàng)建read view 時(shí)生成該版本的事務(wù)已經(jīng)提交,可以被訪問到

如果某個(gè)版本數(shù)據(jù)對(duì)當(dāng)前事務(wù)不可見那么需要一直順著版本鏈找上一個(gè)版本的數(shù)據(jù),并通過上述步驟判斷是否可見,直到找到可見的版本,如果一直找不到說明該條記錄對(duì)當(dāng)前事務(wù)不可見,查詢結(jié)果將不包含該記錄。

2.3 Read Committed和 Repeatable Read的不同

Read Committed——每次讀取數(shù)據(jù)前都生成一個(gè)Read View

這樣可以保證生成Read view 中的m_ids是實(shí)時(shí)活躍事務(wù)id集合,也許第一次讀取的時(shí)候事務(wù)A沒提交,其id位于m_ids中,但是第二次讀取的時(shí)候事務(wù)A提交了,事務(wù)A將不位于m_ids中,這樣在第二次讀取的時(shí)候,通過m_ids判斷事務(wù)A是否提交的時(shí)候,可以得到事務(wù)A已經(jīng)提交了,然后讓事務(wù)A版本產(chǎn)生的數(shù)據(jù)可見(見2.2.4中的內(nèi)容)。

Repeatable Read——如果使用begin開啟事務(wù)那么在第一次查詢的時(shí)候生成Read view,如果使用start transaction with consistent snapshot 那么執(zhí)行的時(shí)候就會(huì)生成read view

這樣可以保證當(dāng)前事務(wù)從頭到尾都是read view中記錄的內(nèi)容是一致的,第一次讀取的時(shí)候事務(wù)A沒有提交,那么不可見,但是第二次讀取的時(shí)候事務(wù)A提交了,但是read view的m_idsmax_trx_id可以判斷事務(wù)A不可見,比如事務(wù)A事務(wù)id小于max_trx_id意味著生成read view是事務(wù)A啟動(dòng)但是沒提交,即使第二次讀事務(wù)A提交了,但是m_ids中還是包含事務(wù)A,那么不可見。如果事務(wù)A事務(wù)id大于max_trx_id,那么自然第二次還是大于max_trx_id,也是不可見的,從而實(shí)現(xiàn)了可重復(fù)讀。

2.4 二級(jí)索引與MVCC

上面我們提到,innodb聚簇索引組織的記錄才具備trx_idroll_point,那么我們使用二級(jí)索引進(jìn)行查詢的時(shí)候,如何判斷數(shù)據(jù)是否可見昵?

  • 二級(jí)索引頁面的page header中存在page_max_trx_id屬性,每當(dāng)有事務(wù)對(duì)其中的記錄進(jìn)行增刪改查操作的時(shí)候,如果事務(wù)的事務(wù)id,大于page_max_trx_id,那么會(huì)更新page_max_trx_id屬性值為其事務(wù)id,這意味著page_max_trx_id記錄了修改該二級(jí)索引頁面最大的事務(wù)id是多少。當(dāng)select通過二級(jí)索引首先看下對(duì)于read view的min_trx_id是否大于該頁面的page_max_trx_id,如果大于那么頁面中所有記錄都對(duì)該read view可見,否則就進(jìn)行下面的第二步
  • 利用二級(jí)索引中的主鍵值,進(jìn)行回標(biāo),得到對(duì)應(yīng)的聚簇索引記錄然后進(jìn)行回表,然后通過2.2中步驟拿到第一個(gè)可見版本的數(shù)據(jù),然后比對(duì)此紀(jì)錄和通過二級(jí)索引查詢得到記錄的值是否相同,如果相同那么發(fā)送給客戶端,否則跳過該記錄。

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

相關(guān)文章

  • mysql?8.0.26?安裝配置方法圖文教程

    mysql?8.0.26?安裝配置方法圖文教程

    這篇文章主要為大家詳細(xì)介紹了mysql?8.0.26?安裝配置方法圖文教程,文中安裝步驟介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-04-04
  • MySQL核心概念及SQL語句與數(shù)據(jù)類型詳解

    MySQL核心概念及SQL語句與數(shù)據(jù)類型詳解

    本文系統(tǒng)梳理MySQL從入門到進(jìn)階的核心知識(shí)體系,從數(shù)據(jù)庫基本概念、表關(guān)系模型到SQL語句分類與語法規(guī)范,重點(diǎn)拆解DDL庫表創(chuàng)建修改與DML增刪改查的實(shí)戰(zhàn)細(xì)節(jié),感興趣的朋友一起看看吧
    2026-05-05
  • Linux7操作系統(tǒng)中如何安裝MySQL5.6

    Linux7操作系統(tǒng)中如何安裝MySQL5.6

    這篇文章主要介紹了Linux7操作系統(tǒng)中如何安裝MySQL5.6問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-09-09
  • 推薦幾款MySQL相關(guān)工具

    推薦幾款MySQL相關(guān)工具

    這篇文章主要介紹了幾款MySQL相關(guān)工具的相關(guān)資料,幫助大家更好的使用和維護(hù)MySQL 數(shù)據(jù)庫,感興趣的朋友可以了解下
    2020-11-11
  • mysql優(yōu)化配置參數(shù)

    mysql優(yōu)化配置參數(shù)

    mysql安裝好需要優(yōu)化配置一下,打開c:\windows\my.ini文件
    2011-03-03
  • 如何通過sql查找所有父節(jié)點(diǎn)和所有子節(jié)點(diǎn)(以mysql為例)

    如何通過sql查找所有父節(jié)點(diǎn)和所有子節(jié)點(diǎn)(以mysql為例)

    這篇文章主要給大家介紹了關(guān)于如何通過sql查找所有父節(jié)點(diǎn)和所有子節(jié)點(diǎn),本文以mysql為例,項(xiàng)目中遇到一個(gè)需求,要求查處菜單節(jié)點(diǎn)的所有節(jié)點(diǎn),這里給大家總結(jié)下,需要的朋友可以參考下
    2023-08-08
  • MySQL Workbench安裝及使用詳解

    MySQL Workbench安裝及使用詳解

    MySQL是一種關(guān)系型數(shù)據(jù)庫管理系統(tǒng),關(guān)系數(shù)據(jù)庫將數(shù)據(jù)保存在不同的表中,而不是將所有數(shù)據(jù)放在一個(gè)大倉庫內(nèi),這樣就增加了速度并提高了靈活性,這篇文章主要介紹了MySQL Workbench安裝及使用,需要的朋友可以參考下
    2022-10-10
  • MySQL數(shù)據(jù)庫中復(fù)合查詢的操作詳解

    MySQL數(shù)據(jù)庫中復(fù)合查詢的操作詳解

    在 MySQL 日常開發(fā)里,單表查詢只能處理最簡(jiǎn)單的數(shù)據(jù)需求,真正的業(yè)務(wù)場(chǎng)景幾乎都要用到復(fù)合查詢,本文就來系統(tǒng)講解一下MySQL復(fù)合查詢的核心技術(shù)與實(shí)戰(zhàn)應(yīng)用吧
    2026-05-05
  • 淺談mysql通配符進(jìn)行模糊查詢的實(shí)現(xiàn)方法

    淺談mysql通配符進(jìn)行模糊查詢的實(shí)現(xiàn)方法

    這篇文章主要介紹了淺談mysql通配符進(jìn)行模糊查詢,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07
  • MySQL數(shù)據(jù)庫基礎(chǔ)命令大全(收藏)

    MySQL數(shù)據(jù)庫基礎(chǔ)命令大全(收藏)

    今天小編給大家整理一下mysql數(shù)據(jù)庫的基礎(chǔ)命令,特此分享到腳本之家平臺(tái),供大家參考下
    2016-12-12

最新評(píng)論

甘孜| 邹城市| 新泰市| 新建县| 新巴尔虎左旗| 拉萨市| 平顶山市| 周宁县| 昌都县| 玛纳斯县| 崇信县| 山西省| 新宁县| 岳阳市| 定边县| 司法| 米易县| 金平| 乐昌市| 台江县| 绥德县| 革吉县| 湾仔区| 潞城市| 肃宁县| 庆城县| 息烽县| 永丰县| 桐庐县| 城市| 两当县| 普宁市| 绿春县| 中方县| 阿拉善右旗| 赣州市| 麦盖提县| 灵川县| 万荣县| 秦安县| 舟山市|