mysql innodb中對MVCC的理解

一、MVCC簡介

MVCC (Multiversion Concurrency Control)芽突,即多版本并發(fā)控制技術(shù),它使得大部分支持行鎖的事務(wù)引擎疾党,不再單純的使用行鎖來進行數(shù)據(jù)庫的并發(fā)控制,取而代之的是把數(shù)據(jù)庫的行鎖與行的多個版本結(jié)合起來猛铅,只需要很小的開銷,就可以實現(xiàn)非鎖定讀陆蟆,從而大大提高數(shù)據(jù)庫系統(tǒng)的并發(fā)性能

讀鎖:也叫共享鎖雷厂、S鎖,若事務(wù)T對數(shù)據(jù)對象A加上S鎖叠殷,則事務(wù)T可以讀A但不能修改A改鲫,其他事務(wù)只能再對A加S鎖,而不能加X鎖林束,直到T釋放A上的S 鎖像棘。這保證了其他事務(wù)可以讀A,但在T釋放A上的S鎖之前不能對A做任何修改诊县。

寫鎖:又稱排他鎖讲弄、X鎖措左。若事務(wù)T對數(shù)據(jù)對象A加上X鎖依痊,事務(wù)T可以讀A也可以修改A,其他事務(wù)不能再對A加任何鎖怎披,直到T釋放A上的鎖胸嘁。這保證了其他事務(wù)在T釋放A上的鎖之前不能再讀取和修改A。

表鎖:操作對象是數(shù)據(jù)表凉逛。Mysql大多數(shù)鎖策略都支持(常見mysql innodb)性宏,是系統(tǒng)開銷最低但并發(fā)性最低的一個鎖策略。事務(wù)t對整個表加讀鎖状飞,則其他事務(wù)可讀不可寫毫胜,若加寫鎖,則其他事務(wù)增刪改都不行诬辈。

行級鎖:操作對象是數(shù)據(jù)表中的一行酵使。是MVCC技術(shù)用的比較多的,但在MYISAM用不了焙糟,行級鎖用mysql的儲存引擎實現(xiàn)而不是mysql服務(wù)器口渔。但行級鎖對系統(tǒng)開銷較大,處理高并發(fā)較好穿撮。

二缺脉、MVCC實現(xiàn)原理

innodb MVCC主要是為Repeatable-Read事務(wù)隔離級別做的痪欲。在此隔離級別下,A攻礼、B客戶端所示的數(shù)據(jù)相互隔離业踢,互相更新不可見

了解innodb的行結(jié)構(gòu)、Read-View的結(jié)構(gòu)對于理解innodb mvcc的實現(xiàn)由重要意義

innodb存儲的最基本row中包含一些額外的存儲信息 DATA_TRX_ID礁扮,DATA_ROLL_PTR陨亡,DB_ROW_ID,DELETE BIT

  • 6字節(jié)的DATA_TRX_ID 標(biāo)記了最新更新這條行記錄的transaction id深员,每處理一個事務(wù)负蠕,其值自動+1

  • 7字節(jié)的DATA_ROLL_PTR 指向當(dāng)前記錄項的rollback segment的undo log記錄,找之前版本的數(shù)據(jù)就是通過這個指針

  • 6字節(jié)的DB_ROW_ID倦畅,當(dāng)由innodb自動產(chǎn)生聚集索引時遮糖,聚集索引包括這個DB_ROW_ID的值,否則聚集索引中不包括這個值.叠赐,這個用于索引當(dāng)中

  • DELETE BIT位用于標(biāo)識該記錄是否被刪除欲账,這里的不是真正的刪除數(shù)據(jù),而是標(biāo)志出來的刪除芭概。真正意義的刪除是在commit的時候

image

具體的執(zhí)行過程

begin->用排他鎖鎖定該行->記錄redo log->記錄undo log->修改當(dāng)前行的值赛不,寫事務(wù)編號,回滾指針指向undo log中的修改前的行

上述過程確切地說是描述了UPDATE的事務(wù)過程罢洲,其實undo log分insert和update undo log踢故,因為insert時,原始的數(shù)據(jù)并不存在惹苗,所以回滾時把insert undo log丟棄即可殿较,而update undo log則必須遵守上述過程

下面分別以select、delete桩蓉、 insert淋纲、 update語句來說明

SELECT

Innodb檢查每行數(shù)據(jù),確保他們符合兩個標(biāo)準:

1院究、InnoDB只查找版本早于當(dāng)前事務(wù)版本的數(shù)據(jù)行(也就是數(shù)據(jù)行的版本必須小于等于事務(wù)的版本)洽瞬,這確保當(dāng)前事務(wù)讀取的行都是事務(wù)之前已經(jīng)存在的,或者是由當(dāng)前事務(wù)創(chuàng)建或修改的行

2业汰、行的刪除操作的版本一定是未定義的或者大于當(dāng)前事務(wù)的版本號伙窃,確定了當(dāng)前事務(wù)開始之前,行沒有被刪除

符合了以上兩點則返回查詢結(jié)果蔬胯。

INSERT

InnoDB為每個新增行記錄當(dāng)前系統(tǒng)版本號作為創(chuàng)建ID对供。

DELETE

InnoDB為每個刪除行的記錄當(dāng)前系統(tǒng)版本號作為行的刪除ID。

UPDATE

InnoDB復(fù)制了一行。這個新行的版本號使用了系統(tǒng)版本號产场。它也把系統(tǒng)版本號作為了刪除行的版本鹅髓。

說明

insert操作時 “創(chuàng)建時間”=DB_ROW_ID,這時京景,“刪除時間 ”是未定義的窿冯;

update時,復(fù)制新增行的“創(chuàng)建時間”=DB_ROW_ID确徙,刪除時間未定義醒串,舊數(shù)據(jù)行“創(chuàng)建時間”不變,刪除時間=該事務(wù)的DB_ROW_ID鄙皇;

delete操作芜赌,相應(yīng)數(shù)據(jù)行的“創(chuàng)建時間”不變,刪除時間=該事務(wù)的DB_ROW_ID伴逸;

select操作對兩者都不修改缠沈,只讀相應(yīng)的數(shù)據(jù)

三、對于MVCC的總結(jié)

上述更新前建立undo log错蝴,根據(jù)各種策略讀取時非阻塞就是MVCC洲愤,undo log中的行就是MVCC中的多版本,這個可能與我們所理解的MVCC有較大的出入顷锰,一般我們認為MVCC有下面幾個特點:

  • 每行數(shù)據(jù)都存在一個版本柬赐,每次數(shù)據(jù)更新時都更新該版本
  • 修改時Copy出當(dāng)前版本隨意修改,各個事務(wù)之間無干擾
  • 保存時比較版本號官紫,如果成功(commit)肛宋,則覆蓋原記錄;失敗則放棄copy(rollback)

就是每行都有版本號万矾,保存時根據(jù)版本號決定是否成功悼吱,聽起來含有樂觀鎖的味道慎框,而Innodb的實現(xiàn)方式是:

  • 事務(wù)以排他鎖的形式修改原始數(shù)據(jù)
  • 把修改前的數(shù)據(jù)存放于undo log良狈,通過回滾指針與主數(shù)據(jù)關(guān)聯(lián)
  • 修改成功(commit)啥都不做,失敗則恢復(fù)undo log中的數(shù)據(jù)(rollback)

二者最本質(zhì)的區(qū)別是笨枯,當(dāng)修改數(shù)據(jù)時是否要排他鎖定薪丁,如果鎖定了還算不算是MVCC?

Innodb的實現(xiàn)真算不上MVCC馅精,因為并沒有實現(xiàn)核心的多版本共存严嗜,undo log中的內(nèi)容只是串行化的結(jié)果,記錄了多個事務(wù)的過程洲敢,不屬于多版本共存漫玄。但理想的MVCC是難以實現(xiàn)的,當(dāng)事務(wù)僅修改一行記錄使用理想的MVCC模式是沒有問題的,可以通過比較版本號進行回滾睦优;但當(dāng)事務(wù)影響到多行數(shù)據(jù)時渗常,理想的MVCC據(jù)無能為力了。

比如汗盘,如果Transaciton1執(zhí)行理想的MVCC皱碘,修改Row1成功,而修改Row2失敗隐孽,此時需要回滾Row1癌椿,但因為Row1沒有被鎖定,其數(shù)據(jù)可能又被Transaction2所修改菱阵,如果此時回滾Row1的內(nèi)容踢俄,則會破壞Transaction2的修改結(jié)果,導(dǎo)致Transaction2違反ACID晴及。

理想MVCC難以實現(xiàn)的根本原因在于企圖通過樂觀鎖代替二段提交褪贵。修改兩行數(shù)據(jù),但為了保證其一致性抗俄,與修改兩個分布式系統(tǒng)中的數(shù)據(jù)并無區(qū)別脆丁,而二提交是目前這種場景保證一致性的唯一手段。二段提交的本質(zhì)是鎖定动雹,樂觀鎖的本質(zhì)是消除鎖定槽卫,二者矛盾,故理想的MVCC難以真正在實際中被應(yīng)用胰蝠,Innodb只是借了MVCC這個名字歼培,提供了讀的非阻塞而已。

參考文章

https://www.percona.com/blog/2014/12/17/innodbs-multi-versioning-handling-can-be-achilles-heel/
http://www.xdata.me/?p=289
http://blogread.cn/it/article/5969
http://blog.csdn.net/chen77716/article/details/6742128
http://blog.chinaunix.net/link.php?url=http://forge.mysql.com%2Fwiki%2FMySQL_Internals

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末茸塞,一起剝皮案震驚了整個濱河市躲庄,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌钾虐,老刑警劉巖噪窘,帶你破解...
    沈念sama閱讀 212,542評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異效扫,居然都是意外死亡倔监,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,596評論 3 385
  • 文/潘曉璐 我一進店門菌仁,熙熙樓的掌柜王于貴愁眉苦臉地迎上來浩习,“玉大人,你說我怎么就攤上這事济丘∑谆啵” “怎么了?”我有些...
    開封第一講書人閱讀 158,021評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長疟赊。 經(jīng)常有香客問我辱士,道長,這世上最難降的妖魔是什么听绳? 我笑而不...
    開封第一講書人閱讀 56,682評論 1 284
  • 正文 為了忘掉前任颂碘,我火速辦了婚禮,結(jié)果婚禮上椅挣,老公的妹妹穿的比我還像新娘头岔。我一直安慰自己,他們只是感情好鼠证,可當(dāng)我...
    茶點故事閱讀 65,792評論 6 386
  • 文/花漫 我一把揭開白布峡竣。 她就那樣靜靜地躺著,像睡著了一般量九。 火紅的嫁衣襯著肌膚如雪适掰。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,985評論 1 291
  • 那天荠列,我揣著相機與錄音类浪,去河邊找鬼。 笑死肌似,一個胖子當(dāng)著我的面吹牛费就,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播川队,決...
    沈念sama閱讀 39,107評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼力细,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了固额?” 一聲冷哼從身側(cè)響起眠蚂,我...
    開封第一講書人閱讀 37,845評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎斗躏,沒想到半個月后逝慧,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,299評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡瑟捣,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,612評論 2 327
  • 正文 我和宋清朗相戀三年馋艺,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片迈套。...
    茶點故事閱讀 38,747評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖碱鳞,靈堂內(nèi)的尸體忽然破棺而出桑李,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 34,441評論 4 333
  • 正文 年R本政府宣布贵白,位于F島的核電站率拒,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏禁荒。R本人自食惡果不足惜猬膨,卻給世界環(huán)境...
    茶點故事閱讀 40,072評論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望呛伴。 院中可真熱鬧勃痴,春花似錦、人聲如沸热康。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,828評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽姐军。三九已至铁材,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間奕锌,已是汗流浹背著觉。 一陣腳步聲響...
    開封第一講書人閱讀 32,069評論 1 267
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留惊暴,地道東北人固惯。 一個月前我還...
    沈念sama閱讀 46,545評論 2 362
  • 正文 我出身青樓,卻偏偏與公主長得像缴守,于是被迫代替她去往敵國和親葬毫。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,658評論 2 350

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