關(guān)于MVCC,我之前寫錯(cuò)了余佃,這次我改好了暮刃!

關(guān)于MVCC的原理,在《我想進(jìn)大廠》之mysql奪命連環(huán)13問寫過一次爆土,但是當(dāng)時(shí)寫的其實(shí)并不準(zhǔn)確椭懊,這個(gè)理解可以應(yīng)付面試,幫助快速理解步势,但是他的真正實(shí)現(xiàn)原理我想再次拿出來說一說氧猬。

簡(jiǎn)單理解版

以下先引用我之前寫過的那篇中的內(nèi)容,可以快速理解坏瘩,建議先簡(jiǎn)單看看盅抚。

要說幻讀,首先要了解MVCC倔矾,MVCC叫做多版本并發(fā)控制泉哈,實(shí)際上就是保存了數(shù)據(jù)在某個(gè)時(shí)間節(jié)點(diǎn)的快照。

我們每行數(shù)據(jù)實(shí)際上隱藏了兩列,創(chuàng)建時(shí)間版本號(hào)丛晦,過期(刪除)時(shí)間版本號(hào),每開始一個(gè)新的事務(wù)提陶,版本號(hào)都會(huì)自動(dòng)遞增烫沙。

還是拿上面的user表舉例子,假設(shè)我們插入兩條數(shù)據(jù)隙笆,他們實(shí)際上應(yīng)該長(zhǎng)這樣锌蓄。

image

這時(shí)候假設(shè)小明去執(zhí)行查詢,此時(shí)current_version=3

select * from user where id<=3;

同時(shí)撑柔,小紅在這時(shí)候開啟事務(wù)去修改id=1的記錄瘸爽,current_version=4

update user set name='張三三' where id=1;

執(zhí)行成功后的結(jié)果是這樣的

image

如果這時(shí)候還有小黑在刪除id=2的數(shù)據(jù),current_version=5铅忿,執(zhí)行后結(jié)果是這樣的剪决。

image

由于MVCC的原理是查找創(chuàng)建版本小于或等于當(dāng)前事務(wù)版本,刪除版本為空或者大于當(dāng)前事務(wù)版本檀训,小明的真實(shí)的查詢應(yīng)該是這樣

select * from user where id<=3 and create_version<=3 and (delete_version>3 or delete_version is null);

所以小明最后查詢到的id=1的名字還是'張三'柑潦,并且id=2的記錄也能查詢到。這樣做是為了保證事務(wù)讀取的數(shù)據(jù)是在事務(wù)開始前就已經(jīng)存在的峻凫,要么是事務(wù)自己插入或者修改的渗鬼。

真正原理

事實(shí)上,上述的說法只是簡(jiǎn)化版的理解荧琼,真正的MVCC用于讀已提交和可重復(fù)讀級(jí)別的控制譬胎,主要通過undo log日志版本鏈和read view來實(shí)現(xiàn)。

每條數(shù)據(jù)隱藏的兩個(gè)字段也并不是創(chuàng)建時(shí)間版本號(hào)過期(刪除)時(shí)間版本號(hào)命锄,而是roll_pointertrx_id堰乔。

roll_pointer指向更新事務(wù)之前生成的undo log,undo log用于事務(wù)的回滾累舷,保證事務(wù)的原子性浩考。

trx_id就是最近一次更新數(shù)據(jù)的事務(wù)ID。

以上述例子來舉例被盈,最初插入兩條數(shù)據(jù)析孽,真實(shí)的情況是這樣,因?yàn)榈谝淮尾迦霐?shù)據(jù)沒有undo log只怎,所以roll_pointer指向一個(gè)空的undo log袜瞬。

image

這時(shí)候假設(shè)小明去執(zhí)行查詢,就會(huì)開啟一個(gè)read view身堡,read view包含幾個(gè)重要的東西邓尤。

  1. m_ids,就是還未提交的事務(wù)id集合
  2. low_limit_id,m_ids里最小的值
  3. up_limit_id汞扎,下一次生成事務(wù)ID最大值
  4. creator_trx_id季稳,創(chuàng)建read view的事務(wù)ID,也就是自己的事務(wù)ID

小明來執(zhí)行查詢了澈魄,當(dāng)前事務(wù)ID=3

select * from user where id<=3;

小紅在這時(shí)候開啟事務(wù)去修改id=1的記錄景鼠,事務(wù)ID=4

update user set name='張三三' where id=1;

這時(shí)候小明的read view是這樣。

m_ids=[3,4]

low_limit_id=3

up_limit_id=5

creator_trx_id=3

所以痹扇,小明在執(zhí)行查詢的時(shí)候铛漓,會(huì)去判斷當(dāng)前這條數(shù)據(jù)的trx_id<read view的low_limit_id,顯然都小于鲫构,所以小明會(huì)正常查詢到id=1,2的兩條記錄浓恶,而不會(huì)受到小紅修改的影響。

這時(shí)候结笨,小紅的修改也完成了包晰,小紅數(shù)據(jù)于是就變成了這樣。

image

如果小明再次去查詢的話禀梳,就會(huì)發(fā)現(xiàn)現(xiàn)在的trx_id>read view的low_limit_id杜窄,也就是4>3,不符合條件算途,同時(shí)發(fā)現(xiàn)現(xiàn)在的trx_id=4在low_limit_id和up_limit_id [3,5]之間塞耕,并且trx_id=4在m_ids=[3,4]之中,所以就會(huì)根據(jù)roll_pointer指向的undo log去查找嘴瓤,trx_id=1小于現(xiàn)在的low_limit_id=3扫外,符合條件,就找到了上一個(gè)版本name=張三的記錄廓脆。

如果這時(shí)候小明自己去修改這條記錄的值筛谚,把名字改成張五,結(jié)果就是這樣停忿。

image

然后小明去查詢的話驾讲,就會(huì)發(fā)現(xiàn)當(dāng)前的trx_id=3就是自己的creator_trx_id,就是自己席赂,那么就直接返回這條數(shù)據(jù)吮铭。

所以,我們可以先總結(jié)下幾種情況:

  1. 如果trx_id<low_limit_id颅停,那么說明就是之前事務(wù)的數(shù)據(jù)谓晌,直接返回,也就對(duì)應(yīng)了小明第一次開啟事務(wù)查詢的場(chǎng)景
  2. 如果trx_id>low_limit癞揉,trx_id還在[low_limit_id,up_limit_id]范圍之內(nèi)纸肉,并且trx_id在m_ids中溺欧,就會(huì)根據(jù)roll_pointer去查找undo log日志鏈,找到之前版本的數(shù)據(jù)柏肪,對(duì)應(yīng)的就是小紅修改后小明再次查詢的場(chǎng)景
  3. 如果trx_id=creator_trx_id姐刁,那么說明就是自己修改的,直接返回就好了烦味,對(duì)應(yīng)的就是小明自己去修改數(shù)據(jù)的場(chǎng)景

不同隔離級(jí)別的實(shí)現(xiàn)

根據(jù)上面闡述的原理龙填,你可能發(fā)現(xiàn)了,這是可重復(fù)讀下的實(shí)現(xiàn)啊拐叉,保證每次讀取到的數(shù)據(jù)都是一致的。

那么扇商,如果是讀已提交級(jí)別下凤瘦,這個(gè)是怎么實(shí)現(xiàn)的?

其實(shí)很簡(jiǎn)單案铺,在上面的原理解釋中蔬芥,我都是假設(shè)每次查詢的時(shí)候生成了read view,后續(xù)并沒有重新生成控汉。

而讀已提交級(jí)別下笔诵,則是每次查詢都會(huì)生成一次read view。

以上述小紅修改過張三后的場(chǎng)景來舉例姑子。

image

在可重復(fù)度級(jí)別下乎婿,由于trx_id>low_limit,trx_id還在[low_limit_id,up_limit_id]范圍之內(nèi)街佑,并且trx_id在m_ids中谢翎,滿足我們上述的條件2,所以就會(huì)根據(jù)roll_pointer找到之前的版本記錄沐旨,保證可重復(fù)讀森逮。

而在讀已提交的級(jí)別下,重新生成了read view磁携,這時(shí)候trx_id不在m_ids之中褒侧,說明事務(wù)已經(jīng)提交,所以可以直接返回這條數(shù)據(jù)谊迄,所以查到的數(shù)據(jù)就是小紅修改后的name=張三三的數(shù)據(jù)了闷供。

總結(jié)

我是艾小仙,我承認(rèn)我浪了鳞上,我之前居然還想浪这吻,我以為年沒過幾天,結(jié)果發(fā)現(xiàn)最近一次技術(shù)文更新是在2月2號(hào)篙议。

我哭唾糯,所以怠硼,我肝了3個(gè)小時(shí),痛定思痛移怯,結(jié)束了我的短暫的王者生涯香璃。

大家覺得還行的話,點(diǎn)個(gè)在看舟误,設(shè)個(gè)星標(biāo)可好葡秒?

我要回到正常更新的頻率中來。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末嵌溢,一起剝皮案震驚了整個(gè)濱河市眯牧,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌赖草,老刑警劉巖学少,帶你破解...
    沈念sama閱讀 211,290評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異秧骑,居然都是意外死亡版确,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門乎折,熙熙樓的掌柜王于貴愁眉苦臉地迎上來绒疗,“玉大人,你說我怎么就攤上這事骂澄∠拍ⅲ” “怎么了?”我有些...
    開封第一講書人閱讀 156,872評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵酗洒,是天一觀的道長(zhǎng)士修。 經(jīng)常有香客問我,道長(zhǎng)樱衷,這世上最難降的妖魔是什么棋嘲? 我笑而不...
    開封第一講書人閱讀 56,415評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮矩桂,結(jié)果婚禮上沸移,老公的妹妹穿的比我還像新娘。我一直安慰自己侄榴,他們只是感情好雹锣,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,453評(píng)論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著癞蚕,像睡著了一般蕊爵。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上桦山,一...
    開封第一講書人閱讀 49,784評(píng)論 1 290
  • 那天攒射,我揣著相機(jī)與錄音醋旦,去河邊找鬼。 笑死会放,一個(gè)胖子當(dāng)著我的面吹牛饲齐,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播咧最,決...
    沈念sama閱讀 38,927評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼捂人,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了矢沿?” 一聲冷哼從身側(cè)響起滥搭,我...
    開封第一講書人閱讀 37,691評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎捣鲸,沒想到半個(gè)月后论熙,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,137評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡摄狱,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,472評(píng)論 2 326
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了无午。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片媒役。...
    茶點(diǎn)故事閱讀 38,622評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖宪迟,靈堂內(nèi)的尸體忽然破棺而出酣衷,到底是詐尸還是另有隱情,我是刑警寧澤次泽,帶...
    沈念sama閱讀 34,289評(píng)論 4 329
  • 正文 年R本政府宣布穿仪,位于F島的核電站,受9級(jí)特大地震影響意荤,放射性物質(zhì)發(fā)生泄漏啊片。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,887評(píng)論 3 312
  • 文/蒙蒙 一玖像、第九天 我趴在偏房一處隱蔽的房頂上張望紫谷。 院中可真熱鬧,春花似錦捐寥、人聲如沸笤昨。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)瞒窒。三九已至,卻和暖如春乡洼,著一層夾襖步出監(jiān)牢的瞬間崇裁,已是汗流浹背匕坯。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留寇壳,地道東北人醒颖。 一個(gè)月前我還...
    沈念sama閱讀 46,316評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像壳炎,于是被迫代替她去往敵國(guó)和親泞歉。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,490評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容