mysql的mvcc 2021-03-22(未允禁轉(zhuǎn))

1.mvcc概要

指Multi-Version Concurrency Control,多版本并發(fā)控制。

  • 設(shè)計目的:解決讀-寫并發(fā)問題稼稿。注意是讀-寫并發(fā),因為一般來說讳窟,一個數(shù)據(jù)如果正被寫入让歼,寫操作是比較耗時的,那么此時讀操作是需要阻塞的丽啡,得等這個寫入結(jié)束了才能讀谋右。mvcc就是用來實現(xiàn)寫數(shù)據(jù)的同時能夠并發(fā)讀的目的。但寫-寫仍然是互斥的补箍。
  • 實現(xiàn)機制:從本質(zhì)上講改执,對【一份數(shù)據(jù)】做到讀寫并發(fā)肯定是不可能的啸蜜,既然一份數(shù)據(jù)搞不定,那就用多份數(shù)據(jù)去做辈挂。數(shù)據(jù)只有一份衬横,而且正在被修改,這個時候來一個讀請求终蒂,你讓它怎么讀蜂林?讀這個狀態(tài)不穩(wěn)定隨時會變化的數(shù)據(jù)?no拇泣。既然一份數(shù)據(jù)做不到讀-寫并發(fā)悉尾,那搞幾個數(shù)據(jù)副本嘛。不管讀還是寫挫酿,都在“自己可見的數(shù)據(jù)副本”上操作,互不影響愕难。這里的副本就是Multi-Version早龟。
  • mvcc工作的事務(wù)隔離級別:read committed, read repearable

2.mvcc的具體實現(xiàn)

mvcc主要依賴隱藏字段,ReadView和undo log實現(xiàn)

2.1 隱藏字段

隱藏字段的主要功能是猫缭,記錄最后一次修改數(shù)據(jù)的事務(wù)葱弟,并且可以追溯歷史版本的數(shù)據(jù)

Internally, InnoDB adds three fields to each row stored in the database:

  • A 6-byte DB_TRX_ID field indicates the transaction identifier for the last transaction that inserted or updated the row. Also, a deletion is treated internally as an update where a special bit in the row is set to mark it as deleted.

  • A 7-byte DB_ROLL_PTR field called the roll pointer. The roll pointer points to an undo log record written to the rollback segment. If the row was updated, the undo log record contains the information necessary to rebuild the content of the row before it was updated.

  • A 6-byte DB_ROW_ID field contains a row ID that increases monotonically as new rows are inserted. If InnoDB generates a clustered index automatically, the index contains row ID values. Otherwise, the DB_ROW_ID column does not appear in any index.

以上介紹來源于MySQL8.0 InnoDB Multi-Versioning
這說明,MySQL8.0里面對每行數(shù)據(jù)加入的隱藏字段有3個:

  • 最后寫事務(wù)的ID: DB_TRX_ID
  • 指向歷史數(shù)據(jù)的回滾指針: DB_ROLL_PTR
  • 數(shù)據(jù)行號: DB_ROW_ID
    其中猜丹,比較重要的是DB_TRX_ID和DB_ROLL_PTR

2.2 ReadView

2.2.1 ReadView基本概念

ReadView芝加,讀視圖,決定了哪些版本的數(shù)據(jù)對事務(wù)可見射窒。換句話說藏杖,事務(wù)是依據(jù)ReadView選擇可見數(shù)據(jù)的,ReadView看得見什么脉顿,事務(wù)就看得見什么蝌麸。ReadView是不同事務(wù)間實現(xiàn)多版本數(shù)據(jù)的根本,我們討論哪些數(shù)據(jù)對特定事務(wù)可見艾疟,其實是在討論哪些數(shù)據(jù)對特定的ReadView可見

2.2.2 ReadView的產(chǎn)生

注意:事務(wù)begin不生成ReadView来吩,一個事務(wù)的ReadView在事務(wù)內(nèi)【執(zhí)行普通select】操作時生成。而且蔽莱,只有普通select語句才會創(chuàng)建ReadView弟疆,select ... lock in share mode,select ... for update不會盗冷,update怠苔、delete、insert語句也不會仪糖,因為它們都是當(dāng)前讀嘀略,會對訪問的數(shù)據(jù)加鎖
以多事務(wù)的update為例:


其中恤溶,// number表示命令的執(zhí)行順序≈难颍可以看到咒程,// 2的update給數(shù)據(jù)上鎖之后,// 3就會一直等待

讀提交和可重復(fù)讀讼育,實際上就是通過ReadView的不同機制實現(xiàn)的帐姻。

  • 在讀提交隔離級別中,事務(wù)內(nèi)每次普通select都即時產(chǎn)生一個ReadView奶段,因此可以讀到別的事務(wù)已經(jīng)提交的數(shù)據(jù)饥瓷;
  • 而在可重復(fù)讀隔離級別中,事務(wù)的首次普通select產(chǎn)生一個ReadView痹籍,并且這個ReadView用于事務(wù)內(nèi)后續(xù)所有的普通select呢铆,從而實現(xiàn)可重復(fù)讀

2.2.3 ReadView的數(shù)據(jù)結(jié)構(gòu)

下面來看一下ReadView究竟長什么樣

ReadView主要依賴以下幾個字段:

  • creator_trx_id 當(dāng)前創(chuàng)建的事務(wù)ID,全局遞增《撞現(xiàn)在設(shè)當(dāng)前創(chuàng)建的事務(wù)為T棺克,首次select產(chǎn)生的ReadView為rv
  • up_limit_id 在事務(wù)T產(chǎn)生rv的那一時刻,距離事務(wù)T的【最遠(yuǎn)】【活躍】事務(wù)ID线定。最遠(yuǎn)即事務(wù)編號最小娜谊。
  • low_limit_id 在事務(wù)T產(chǎn)生rv的那一時刻,【全局】事務(wù)范圍內(nèi)【下一個】將被分配的事務(wù)ID斤讥,也就是未被分配的最小事務(wù)編號纱皆。例如,此刻全局的所有事務(wù)已經(jīng)編號到999了芭商,那么1000就作為rv的low_limit_id派草。
  • trx_ids。up_limit_id和low_limit_id是左閉右開的關(guān)系铛楣,即[up_limit_id, low_limit_id)澳眷,我們把這個區(qū)間內(nèi)的除事務(wù)T自己外的活動事務(wù)記為trx_ids,表示事務(wù)T的rv視圖不可見的其他活躍事務(wù)蛉艾。

ReadView的核心是trx_ids钳踊。

遍歷所有record,記遍歷到的當(dāng)前record的DB_TRX_ID為t_id

    1. if t_id out of [up_limit_id, low_limit_id)
      要么是id < up_limit_id勿侯,即修改當(dāng)前record的事務(wù)已經(jīng)commit拓瞪,顯然已完成事務(wù)的數(shù)據(jù)更改是對rv可見的;
      要么是id >= low_limit_id助琐,即在rv產(chǎn)生后才創(chuàng)建的事務(wù)祭埂,這些事務(wù)對record的修改在rv的未來發(fā)生,對rv不可見,那么就順著record的DB_ROLL_PTR一直找到rv可見的歷史版本數(shù)據(jù)
    1. else up_limit_id <= t_id < low_limit_id
      此時如果t_id in trx_ids蛆橡,就表明最后修改該record的事務(wù)在rv創(chuàng)建時處于活躍狀態(tài)中舌界,也就是說t_id和T在rv創(chuàng)建時刻是并行活躍的,出于事務(wù)間的獨立性泰演,該record對rv不可見呻拌,那么就順著record的DB_ROLL_PTR一直找到rv可見的歷史版本數(shù)據(jù)
      否則,t_id not in trx_ids睦焕,說明在rv產(chǎn)生的時候藐握,最后修改該record的事務(wù)早已經(jīng)提交了,因此record對rv可見

2.3 Undo log

Undo log以鏈表形式存儲了歷史版本數(shù)據(jù)垃喊,如果當(dāng)前記錄行對事務(wù)不可見猾普,需要順著undo log鏈找到滿足其可見性條件的記錄行版本

3. 例子

基于ReadView的MySQL mvcc例子

本圖例來自MySQL中MVCC的正確打開方式(源碼佐證),本文整理的內(nèi)容也參考了其中的內(nèi)容本谜。還是要多看官方文檔初家,多看源碼,比啥都強

--
補充:
個人理解乌助,mvcc最樸素的思想還是【一寫多讀】溜在,寫操作只有一個版本,而讀操作可以有多個版本眷茁。類似針對數(shù)據(jù)的“主寫從讀”思想,一主(最新版本數(shù)據(jù)纵诞,用于寫)多從(多份歷史版本數(shù)據(jù)上祈,用于讀)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市浙芙,隨后出現(xiàn)的幾起案子登刺,更是在濱河造成了極大的恐慌,老刑警劉巖嗡呼,帶你破解...
    沈念sama閱讀 221,635評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件纸俭,死亡現(xiàn)場離奇詭異,居然都是意外死亡南窗,警方通過查閱死者的電腦和手機揍很,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來万伤,“玉大人窒悔,你說我怎么就攤上這事宛徊⊙该” “怎么了?”我有些...
    開封第一講書人閱讀 168,083評論 0 360
  • 文/不壞的土叔 我叫張陵惭墓,是天一觀的道長虹钮。 經(jīng)常有香客問我聋庵,道長膘融,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,640評論 1 296
  • 正文 為了忘掉前任祭玉,我火速辦了婚禮氧映,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘攘宙。我一直安慰自己屯耸,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 68,640評論 6 397
  • 文/花漫 我一把揭開白布蹭劈。 她就那樣靜靜地躺著疗绣,像睡著了一般。 火紅的嫁衣襯著肌膚如雪铺韧。 梳的紋絲不亂的頭發(fā)上多矮,一...
    開封第一講書人閱讀 52,262評論 1 308
  • 那天,我揣著相機與錄音哈打,去河邊找鬼塔逃。 笑死,一個胖子當(dāng)著我的面吹牛料仗,可吹牛的內(nèi)容都是我干的湾盗。 我是一名探鬼主播,決...
    沈念sama閱讀 40,833評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼立轧,長吁一口氣:“原來是場噩夢啊……” “哼格粪!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起氛改,我...
    開封第一講書人閱讀 39,736評論 0 276
  • 序言:老撾萬榮一對情侶失蹤帐萎,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后胜卤,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體疆导,經(jīng)...
    沈念sama閱讀 46,280評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,369評論 3 340
  • 正文 我和宋清朗相戀三年葛躏,在試婚紗的時候發(fā)現(xiàn)自己被綠了澈段。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,503評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡舰攒,死狀恐怖均蜜,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情芒率,我是刑警寧澤囤耳,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響充择,放射性物質(zhì)發(fā)生泄漏德玫。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,870評論 3 333
  • 文/蒙蒙 一椎麦、第九天 我趴在偏房一處隱蔽的房頂上張望宰僧。 院中可真熱鬧,春花似錦观挎、人聲如沸琴儿。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽造成。三九已至,卻和暖如春雄嚣,著一層夾襖步出監(jiān)牢的瞬間晒屎,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評論 1 272
  • 我被黑心中介騙來泰國打工缓升, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留鼓鲁,地道東北人。 一個月前我還...
    沈念sama閱讀 48,909評論 3 376
  • 正文 我出身青樓港谊,卻偏偏與公主長得像骇吭,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子歧寺,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,512評論 2 359

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