Mysql MVCC原理和鎖詳解

一鼻疮、什么是MVCC?

??MVCC(Multi-Version Concurrency Control)多版本并發(fā)控制琳轿,是確保在高并發(fā)下判沟,多個(gè)事務(wù)讀取數(shù)據(jù)時(shí)不加鎖也可以多次讀取相同的值。MVCC在讀已提交(READ COMMITTED)崭篡、可重復(fù)讀(REPEATABLE READ 簡稱RR)模式下才生效挪哄。

二、MVCC解決了事務(wù)的什么問題琉闪?

在并發(fā)事務(wù)下迹炼,可能會(huì)產(chǎn)生如下問題:
1.臟讀 :當(dāng)前事務(wù)讀取到其它事務(wù)未提交的數(shù)據(jù)。
2.臟寫 : 事務(wù)B提交后颠毙,將事務(wù)A提交的數(shù)據(jù)覆蓋斯入。
3.不可重復(fù)讀:在同一個(gè)事務(wù)中砂碉,不同時(shí)間段執(zhí)行相同的查詢語句,得到的結(jié)果集不相同咱扣。
4.幻讀:事務(wù)A讀取到了事務(wù)B新增的數(shù)據(jù)绽淘。

MVCC可重復(fù)讀模式下,解決了事務(wù)的臟讀闹伪、臟寫沪铭、不可重復(fù)讀等問題,但是還是存在幻讀問題偏瓤,幻讀問題可以使用間隙鎖進(jìn)行解決杀怠。

三、MVCC的實(shí)現(xiàn)原理

3.1 undo log文件

??MVCC是通過歷史操作快照的版本鏈進(jìn)行實(shí)現(xiàn)的厅克,這個(gè)版本鏈實(shí)際上就是undo log的記錄的數(shù)據(jù)赔退。
??undo log里面通過兩個(gè)隱藏字段trx_id、roll_pointer將這些數(shù)據(jù)串聯(lián)起來证舟,形成一個(gè)歷史版本鏈硕旗。當(dāng)事務(wù)需要回滾或事務(wù)需要執(zhí)行select語句時(shí),都是通過undo log里面的roll_pointer去查找對(duì)應(yīng)版本的數(shù)據(jù)女责。

3.2 read view一致性視圖

??當(dāng)事務(wù)要執(zhí)行查詢sql時(shí)漆枚,會(huì)生成一個(gè)一致性視圖,也就是read view抵知,read view由當(dāng)前所有未提交的事務(wù)ID組成的一個(gè)數(shù)組墙基,和已創(chuàng)建的最大事務(wù)id構(gòu)成。
??在這個(gè)數(shù)組中刷喜,最小的事務(wù)id稱為min_id,最大的事務(wù)id稱為max_id,當(dāng)要查詢歷史數(shù)據(jù)時(shí)残制,需要通過對(duì)比事務(wù)的id才能區(qū)分哪些版本的數(shù)據(jù)可以展示,哪些數(shù)據(jù)不能展示掖疮。
示例:read view = [100,101],300;
其中初茶,Min_id = 100、Max_id = 300氮墨。100和101都屬于未提交的活躍事務(wù)纺蛆。

在可重復(fù)讀模式下,只會(huì)在第一次執(zhí)行查詢語句時(shí)生成read view规揪,而在讀已提交模式下桥氏,每次查詢都會(huì)生成一個(gè)read view。

3.3 redo log 版本鏈對(duì)比規(guī)則

Mysql將整個(gè)版本鏈的數(shù)據(jù)劃分為三個(gè)區(qū)間:

數(shù)據(jù)區(qū)間

如果trx_id < min_id猛铅,那么表示這個(gè)事務(wù)是屬于已提交的事務(wù),數(shù)據(jù)是可見的字支。
如果trx_id > max_id,那么標(biāo)識(shí)這個(gè)事務(wù)是屬于將來要開啟的,數(shù)據(jù)是不可見的堕伪。
如果min_id <= trx_id <= max_id 揖庄,就要分為兩種情況:
??a.如果trx_id在read view數(shù)組中,那么就表示當(dāng)前trx_id屬于未提交的事務(wù)欠雌,數(shù)據(jù)是不可見的蹄梢。
??b.如果trx_id不在read view數(shù)組中,那么當(dāng)前trx_id就是屬于已提交的事務(wù)富俄,數(shù)據(jù)是可見的禁炒。

??正是有了MVCC機(jī)制,讓多個(gè)事務(wù)對(duì)同一條數(shù)據(jù)進(jìn)行讀寫時(shí)霍比,不需要加鎖也不會(huì)出現(xiàn)讀寫沖突幕袱。事務(wù)A每次讀的都是歷史版本的快照,而事務(wù)B修改的數(shù)據(jù)悠瞬,則會(huì)稱為這個(gè)版本鏈的最新數(shù)據(jù)们豌,通過上面的對(duì)比規(guī)則,其它事務(wù)是不會(huì)讀取到最新的已修改的值浅妆。
??但是MVCC沒有解決幻讀問題望迎,對(duì)于其它事務(wù)新增的數(shù)據(jù),雖然讀不到凌外,但是仍然可以感知到新增的數(shù)據(jù)擂煞,比如對(duì)新增數(shù)據(jù)進(jìn)行修改操作。在可重復(fù)讀模式下趴乡,可以使用間隙鎖進(jìn)行解決幻讀問題。

3.4 間隙鎖 Gap Lock

間隙鎖可以理解成范圍鎖蝗拿,鎖的是兩個(gè)值之間的范圍晾捏,其它事務(wù)無法對(duì)范圍內(nèi)的數(shù)據(jù)進(jìn)行新增和修改。
比如事務(wù)A當(dāng)前的間隙鎖的值是7-10哀托,但是目前數(shù)據(jù)庫中并不存在id =8的數(shù)據(jù)惦辛,事務(wù)B想要新增id =8的數(shù)據(jù),此時(shí)是無法新增的仓手,這樣就可以解決幻讀問題胖齐。

四、數(shù)據(jù)庫中的鎖

4.1 數(shù)據(jù)庫的鎖是什么嗽冒?

在并發(fā)場(chǎng)景下呀伙,鎖是協(xié)調(diào)并發(fā)訪問資源的一種手段,通過加鎖阻塞方式添坊,讓一個(gè)資源在同一時(shí)刻只能有一個(gè)客戶端去訪問剿另。

4.2 鎖的分類

a.從性能上分
悲觀鎖:對(duì)要訪問的資源直接加鎖
樂觀鎖:通過版本對(duì)比的方式來實(shí)現(xiàn),不會(huì)對(duì)訪問的資源加鎖
b.從操作類型分
讀鎖(shared 共享鎖):針對(duì)同一行數(shù)據(jù),可以允許多個(gè)讀雨女,但是會(huì)阻塞寫鎖谚攒。
寫鎖(exclusive 排它鎖):對(duì)于同一行數(shù)據(jù),會(huì)阻塞其它事務(wù)的讀和寫氛堕。
c.從鎖的粒度上分
表鎖:開銷小馏臭、加鎖快,不會(huì)出現(xiàn)死鎖問題讼稚,鎖的粒度大括儒,并發(fā)度低。
行鎖:開銷大乱灵、加鎖慢塑崖,會(huì)出現(xiàn)死鎖問題,鎖的粒度小痛倚,并發(fā)度高规婆。
一句話總結(jié):讀鎖不會(huì)阻塞讀,會(huì)阻塞寫蝉稳;寫鎖會(huì)阻塞讀寫抒蚜。
行鎖:InnoDB中的行鎖是加在索引上的,不是針對(duì)數(shù)據(jù)行進(jìn)行加鎖耘戚。如果該索引失效嗡髓,行鎖會(huì)升級(jí)成表鎖。

五收津、總結(jié)

MVCC:
1饿这、MVCC在不加鎖的情況下,解決了并發(fā)事務(wù)的臟讀撞秋、臟寫不可重復(fù)度等問題长捧,而幻讀可以使用間隙鎖進(jìn)行解決。
2吻贿、undo log里面通過兩個(gè)隱藏字段trx_id串结、roll_pointer將歷史快照數(shù)據(jù)串聯(lián)起來,形成一個(gè)版本鏈舅列,是read view獲取數(shù)據(jù)的前提肌割。
3、read view是在第一次查詢時(shí)生成的帐要,由所有未提交的活躍事務(wù)id組成的數(shù)組和最大事務(wù)id構(gòu)成把敞。
4、通過對(duì)比事務(wù)id的大小宠叼,將數(shù)據(jù)進(jìn)行展示先巴。

鎖:
InnoDB中其爵,行鎖是加在索引上,因此要注意索引的失效問題伸蚯,否則行鎖升級(jí)成表鎖摩渺。
盡量減少條件檢索范圍,避免間隙鎖的范圍過大剂邮,降低并發(fā)力度摇幻。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市挥萌,隨后出現(xiàn)的幾起案子绰姻,更是在濱河造成了極大的恐慌,老刑警劉巖引瀑,帶你破解...
    沈念sama閱讀 210,978評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件狂芋,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡憨栽,警方通過查閱死者的電腦和手機(jī)帜矾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來屑柔,“玉大人屡萤,你說我怎么就攤上這事〉穑” “怎么了死陆?”我有些...
    開封第一講書人閱讀 156,623評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長唧瘾。 經(jīng)常有香客問我措译,道長,這世上最難降的妖魔是什么饰序? 我笑而不...
    開封第一講書人閱讀 56,324評(píng)論 1 282
  • 正文 為了忘掉前任瞳遍,我火速辦了婚禮,結(jié)果婚禮上菌羽,老公的妹妹穿的比我還像新娘。我一直安慰自己由缆,他們只是感情好注祖,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,390評(píng)論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著均唉,像睡著了一般是晨。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上舔箭,一...
    開封第一講書人閱讀 49,741評(píng)論 1 289
  • 那天罩缴,我揣著相機(jī)與錄音蚊逢,去河邊找鬼。 笑死箫章,一個(gè)胖子當(dāng)著我的面吹牛烙荷,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播檬寂,決...
    沈念sama閱讀 38,892評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼终抽,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了桶至?” 一聲冷哼從身側(cè)響起昼伴,我...
    開封第一講書人閱讀 37,655評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎镣屹,沒想到半個(gè)月后圃郊,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,104評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡女蜈,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年持舆,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片鞭光。...
    茶點(diǎn)故事閱讀 38,569評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡吏廉,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出惰许,到底是詐尸還是另有隱情席覆,我是刑警寧澤,帶...
    沈念sama閱讀 34,254評(píng)論 4 328
  • 正文 年R本政府宣布汹买,位于F島的核電站佩伤,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏晦毙。R本人自食惡果不足惜生巡,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,834評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望见妒。 院中可真熱鬧孤荣,春花似錦、人聲如沸须揣。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽耻卡。三九已至疯汁,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間卵酪,已是汗流浹背谤碳。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評(píng)論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留溢豆,地道東北人蜒简。 一個(gè)月前我還...
    沈念sama閱讀 46,260評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像沫换,于是被迫代替她去往敵國和親臭蚁。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,446評(píng)論 2 348

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