Mysql中的MVCC機制

MVCC(Multi-Version Concurrency Control)肪获,多版本并發(fā)控制寝凌。

MVCC是一種并發(fā)控制的方法,通過維護數(shù)據(jù)多個版本的記錄孝赫,以無鎖的方式解決并發(fā)讀寫沖突较木。目的就是規(guī)避在讀寫沖突的時候進行加鎖的操作。Mysql的Innodb引擎就使用了MVCC青柄。

相關概念

要了解MVCC的實現(xiàn)機制伐债,需要先知道Mysql中以下幾個概念。

事物ID和DB_TRX_ID

事物ID

我們都知道innodb是支持事物的致开,在innodb中每一個事物創(chuàng)建時都會分配一個自增的ID作為事物為唯一標志峰锁,也就是事物ID。

DB_TRX_ID

數(shù)據(jù)表里每一行數(shù)據(jù)都會有一個隱藏字段DB_TRX_ID双戳,用來存儲創(chuàng)建或者最后一次修改此記錄的事物ID

undo log和DB_ROLL_PTR

DB_ROLL_PTR

數(shù)據(jù)表里另外一個隱藏字段虹蒋,DB_ROLL_PTR回滾指針,指向這條記錄的上一個版本在undo log中的數(shù)據(jù)。

undo log

undo log存儲每行記錄的修改歷史魄衅∏涂ⅲ可以簡單理解undo log是一個與數(shù)據(jù)表結構相同的另外一張表,數(shù)據(jù)表的數(shù)據(jù)行字段它都有晃虫,數(shù)據(jù)表的行記錄每修改一次皆撩,就將這行數(shù)據(jù)的當前記錄寫到undo log中,并將返回的undo log指針地址寫入DB_ROLL_PTR傲茄,然后修改數(shù)據(jù)行數(shù)據(jù)毅访、更新事物ID听隐。

undo log主要分為兩種:

insert undo log
代表事務在insert新記錄時產(chǎn)生的undo log, 只在事務回滾時需要潮孽,并且在事務提交后可以被立即丟棄
update undo log
事務在進行update或delete時產(chǎn)生的undo log; 不僅在事務回滾時需要掏呼,在快照讀時也需要;所以不能隨便刪除草巡,只有在快速讀或事務回滾不涉及該日志時,對應的日志才會被purge線程統(tǒng)一清除

結構大概如下圖所示:

圖片來源:http://www.reibang.com/p/8845ddca3b23

undo log可以作為mvcc中查找對應可讀記錄型酥,也可以作為當前事物的rollback依據(jù)山憨。
undo log也并不是無限增長的,會有另外一個線程會嘗試清除早期的undo log記錄弥喉,因為他們已經(jīng)沒有用處了郁竟。

當前讀與快照讀

當前讀

當前讀指的是讀取數(shù)據(jù)當前最新數(shù)據(jù)。update由境、insert棚亩、delete、select for update(排他鎖)虏杰、select lock in share mode讥蟆。讀取數(shù)據(jù)需要保證其他并發(fā)事務不能修改當前記錄,會對讀取的記錄進行加鎖纺阔。

快照讀

快照讀指的是在讀取數(shù)據(jù)時瘸彤,生成讀取快照,在同一個事物中可能會一直讀取此快照的數(shù)據(jù)笛钝≈士觯快照讀讀到的數(shù)據(jù)可能不是最新的,可能是歷史版本的數(shù)據(jù)玻靡,這些歷史版本的數(shù)據(jù)就是從undo log中獲取的结榄。
事物中的select 不加鎖的情況會執(zhí)行快照讀,快照讀依賴readview來實現(xiàn)啃奴。
快照讀的前提是隔離級別不是串行級別潭陪,串行級別下的快照讀會退化成當前讀。

ReadView

讀視圖,由當前活躍事物ID的列表trx_list依溯、當前活躍最小事物ID low_limit_id老厌、下一個即將分配的事物ID up_limit_id,三個部分組成黎炉。

事物間可見性分析

基于ReadView的可見性分析邏輯

執(zhí)行快照讀的時候枝秤,會創(chuàng)建一個ReadView。定義被讀取行的DB_TRX_ID 為trx_id慷嗜。

  1. 比較 trx_id是否小于low_limit_id 或者為當前事物ID淀弹,如果為true,則代表修改此行數(shù)據(jù)的事物早已提交或者就是當前事務進行的修改庆械,當前記錄可見薇溃。否則進入下一步判斷。
  2. 比較trx_id是否大于等于up_limit_id缭乘,如果為true沐序,則代表修改此行記錄的事物晚于當前讀視圖創(chuàng)建,當前記錄不可見堕绩,根據(jù)DB_ROLL_PTR undo log指針找到上一條記錄策幼,從新進行可見性分析。否則進入下一步判斷
  3. 判斷trx_id是否在trx_list列表中奴紧,如果在特姐,代表修改此行記錄的事物還未提交,當前事務不可以讀取當前記錄黍氮,根據(jù)DB_ROLL_PTR undo log指針找到上一條記錄唐含,從新進行可見性分析。否則說明數(shù)據(jù)在readview生成的時候已經(jīng)提交滤钱,當期事物可以讀取當前記錄觉壶。

數(shù)據(jù)庫事物隔離級別與MVCC

  • 臟讀
    讀到了別的事物未提交的數(shù)據(jù),由于別的事物有可能會回滾件缸,相當于讀到了錯誤的數(shù)據(jù)铜靶。
  • 不可重復讀
    讀到了別的事物已提交的數(shù)據(jù),在當前事務中他炊,前后兩次的讀取可能數(shù)據(jù)不一致争剿。
  • 幻讀
    也是讀到了別的事物已提交的數(shù)據(jù),在當前事務中痊末,前后兩次的讀取可能數(shù)據(jù)不一致蚕苇。與不重復讀區(qū)別是,幻讀指的是insert或delete產(chǎn)生的不一致凿叠,而不可重讀指的是update產(chǎn)生的不一致涩笤。

數(shù)據(jù)庫為了解決臟讀嚼吞、不可重復讀、幻讀蹬碧,定義了事物間的隔離級別舱禽。

事物隔離級別
  • 串行化Serializable
    一切指令同步執(zhí)行,也就沒有以上的問題了恩沽√苤桑可以解決臟讀、幻讀罗心、不可重讀里伯。
  • 可重復讀Repeat Read、RR
    在同一事物中讀取被修改的記錄渤闷,總是一致的疾瓮。可以解決臟讀飒箭、不可重復讀爷贫。
  • 讀已提交Read Committed、RC
    可以讀取別的事物已經(jīng)提交的數(shù)據(jù)补憾。可以解決臟讀卷员。
  • 讀未提交Read UnCommitted
    可以讀到別的事物未提交的數(shù)據(jù)盈匾。啥問題都沒解決。

隔離級別是約嚴格需要的約束越多毕骡,相對的性能就會越差削饵。
Mysql Innodb的默認數(shù)據(jù)庫隔離級別為RR。
Oracle的隔離級別只支持Serializable和RC未巫,另外提供了一種只讀的模式窿撬,只允許select。

事物隔離級別與MVCC

在RR級別下叙凡,事物進行快照讀時會檢查當前事物是否已經(jīng)創(chuàng)建過ReadView劈伴,如果存在,則使用已經(jīng)創(chuàng)建的握爷,這也是實現(xiàn)可重復的方法跛璧。
在RC級別下,事物每一次快照讀都會創(chuàng)建一個新的ReadView新啼,這樣就會造成不可重復的和幻讀的問題追城。

Innodb利用MVCC解決了RR級別下快照讀中的幻讀問題,當前讀中的幻讀問題需要使用GAP lock解決燥撞,也就是間隙鎖座柱。
舉個例子:

創(chuàng)建user表迷帜,自增主鍵ID、name色洞、age戏锹,三個字段;
插入兩條數(shù)據(jù)1-張三-10锋玲、2-李四-20景用;

image.png

啟動事物1,查詢name=張三的記錄惭蹂,會返回1-張三伞插;
啟動事物2,新增記錄3-張三-30盾碗;
在事物1中再次查詢name=張三的記錄媚污,仍然返回1-張三;
在事物1中修改name=張三的age=45廷雅,提交耗美;會發(fā)現(xiàn)1、3的age都會變?yōu)?5航缀。

image.png

這就是解決了快照讀的幻讀商架,而修改操作屬于當前讀,仍然有幻讀的問題芥玉。
但是如果這里將事物2的提交事務延遲到事物1修改數(shù)據(jù)之后蛇摸,會發(fā)現(xiàn)事物1的修改數(shù)據(jù)會被卡住。

這里就使用了間隙鎖進行防止寫的幻讀灿巧。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末赶袄,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子抠藕,更是在濱河造成了極大的恐慌饿肺,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,589評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件盾似,死亡現(xiàn)場離奇詭異敬辣,居然都是意外死亡,警方通過查閱死者的電腦和手機颜说,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,615評論 3 396
  • 文/潘曉璐 我一進店門购岗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人门粪,你說我怎么就攤上這事喊积。” “怎么了玄妈?”我有些...
    開封第一講書人閱讀 165,933評論 0 356
  • 文/不壞的土叔 我叫張陵乾吻,是天一觀的道長髓梅。 經(jīng)常有香客問我,道長绎签,這世上最難降的妖魔是什么枯饿? 我笑而不...
    開封第一講書人閱讀 58,976評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮诡必,結果婚禮上奢方,老公的妹妹穿的比我還像新娘。我一直安慰自己爸舒,他們只是感情好蟋字,可當我...
    茶點故事閱讀 67,999評論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著扭勉,像睡著了一般鹊奖。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上涂炎,一...
    開封第一講書人閱讀 51,775評論 1 307
  • 那天忠聚,我揣著相機與錄音,去河邊找鬼唱捣。 笑死两蟀,一個胖子當著我的面吹牛,可吹牛的內容都是我干的震缭。 我是一名探鬼主播垫竞,決...
    沈念sama閱讀 40,474評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼蛀序!你這毒婦竟也來了?” 一聲冷哼從身側響起活烙,我...
    開封第一講書人閱讀 39,359評論 0 276
  • 序言:老撾萬榮一對情侶失蹤徐裸,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后啸盏,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體重贺,經(jīng)...
    沈念sama閱讀 45,854評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,007評論 3 338
  • 正文 我和宋清朗相戀三年回懦,在試婚紗的時候發(fā)現(xiàn)自己被綠了气笙。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,146評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡怯晕,死狀恐怖潜圃,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情舟茶,我是刑警寧澤谭期,帶...
    沈念sama閱讀 35,826評論 5 346
  • 正文 年R本政府宣布堵第,位于F島的核電站,受9級特大地震影響隧出,放射性物質發(fā)生泄漏踏志。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,484評論 3 331
  • 文/蒙蒙 一胀瞪、第九天 我趴在偏房一處隱蔽的房頂上張望针余。 院中可真熱鬧,春花似錦凄诞、人聲如沸圆雁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,029評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽摸柄。三九已至,卻和暖如春既忆,著一層夾襖步出監(jiān)牢的瞬間驱负,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,153評論 1 272
  • 我被黑心中介騙來泰國打工患雇, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留跃脊,地道東北人。 一個月前我還...
    沈念sama閱讀 48,420評論 3 373
  • 正文 我出身青樓苛吱,卻偏偏與公主長得像酪术,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子翠储,可洞房花燭夜當晚...
    茶點故事閱讀 45,107評論 2 356

推薦閱讀更多精彩內容