InnoDB事務(wù)隔離級(jí)別實(shí)現(xiàn)原理

數(shù)據(jù)庫(kù)一般都會(huì)并發(fā)執(zhí)行多個(gè)事務(wù)匪燕,多個(gè)事務(wù)可能會(huì)并發(fā)的對(duì)相同的一批數(shù)據(jù)進(jìn)行增刪改查操作蕾羊,可能就會(huì)導(dǎo)致我們說(shuō)的臟寫、臟讀帽驯、不可重復(fù)讀龟再、幻讀這些問(wèn)題。

這些問(wèn)題的本質(zhì)都是數(shù)據(jù)庫(kù)的多事務(wù)并發(fā)問(wèn)題尼变,為了解決多事務(wù)并發(fā)問(wèn)題利凑,數(shù)據(jù)庫(kù)設(shè)計(jì)了事務(wù)隔離機(jī)制浆劲、鎖機(jī)制、MVCC多版本并發(fā)控制隔離機(jī)制哀澈,用一整套機(jī)制來(lái)解決多事務(wù)并發(fā)問(wèn)題牌借。

1.并發(fā)事務(wù)帶來(lái)的問(wèn)題以及事務(wù)隔離級(jí)別

并發(fā)事務(wù)處理帶來(lái)的問(wèn)題:

  • 更新丟失(Lost Update)或臟寫
      當(dāng)兩個(gè)或多個(gè)事務(wù)選擇同一行,然后基于最初選定的值更新該行時(shí)割按,由于每個(gè)事務(wù)都不知道其他事務(wù)的存在膨报,就會(huì)發(fā)生丟失更新問(wèn)題–最后的更新覆蓋了由其他事務(wù)所做的更新。
  • 臟讀(Dirty Reads)
      一個(gè)事務(wù)正在對(duì)一條記錄做修改适荣,在這個(gè)事務(wù)完成并提交前现柠,這條記錄的數(shù)據(jù)就處于不一致的狀態(tài);這時(shí)弛矛,另一個(gè)事務(wù)也來(lái)讀取同一條記錄够吩,如果不加控制,第二個(gè)事務(wù)讀取了這些“臟”數(shù)據(jù)丈氓,并據(jù)此作進(jìn)一步的處理周循,就會(huì)產(chǎn)生未提交的數(shù)據(jù)依賴關(guān)系。這種現(xiàn)象被形象的叫做“臟讀”扒寄。
      一句話:事務(wù)A讀取到了事務(wù)B已經(jīng)修改但尚未提交的數(shù)據(jù)鱼鼓,還在這個(gè)數(shù)據(jù)基礎(chǔ)上做了操作。此時(shí)该编,如果B事務(wù)回滾迄本,A讀取的數(shù)據(jù)無(wú)效,不符合一致性要求课竣。
  • 不可重讀(Non-Repeatable Reads)
      一個(gè)事務(wù)在讀取某些數(shù)據(jù)后的某個(gè)時(shí)間嘉赎,再次讀取以前讀過(guò)的數(shù)據(jù),卻發(fā)現(xiàn)其讀出的數(shù)據(jù)已經(jīng)發(fā)生了改變于樟、或某些記錄已經(jīng)被刪除了公条!這種現(xiàn)象就叫做“不可重復(fù)讀”。
      一句話:事務(wù)A內(nèi)部的相同查詢語(yǔ)句在不同時(shí)刻讀出的結(jié)果不一致迂曲,不符合隔離性
  • 幻讀(Phantom Reads)
      一個(gè)事務(wù)按相同的查詢條件重新讀取以前檢索過(guò)的數(shù)據(jù)靶橱,卻發(fā)現(xiàn)其他事務(wù)插入了滿足其查詢條件的新數(shù)據(jù),這種現(xiàn)象就稱為“幻讀”路捧。
      一句話:事務(wù)A讀取到了事務(wù)B提交的新增數(shù)據(jù)关霸,不符合隔離性

上述“臟讀”、“不可重復(fù)讀”和“幻讀”可以通過(guò)不同的事務(wù)隔離級(jí)別來(lái)解決:


2.RC RR隔離級(jí)別是怎樣實(shí)現(xiàn)的杰扫?

在可重復(fù)讀隔離級(jí)別Repeatable read队寇,當(dāng)事務(wù)開啟,執(zhí)行任何查詢sql時(shí)會(huì)生成當(dāng)前事務(wù)的一致性視圖read-view章姓,該視圖在事務(wù)結(jié)束之前都不會(huì)變化佳遣,這個(gè)視圖由執(zhí)行查詢時(shí)所有未提交事務(wù)id數(shù)組(數(shù)組里最小的id為min_id)和已創(chuàng)建的最大事務(wù)id(max_id)組成识埋,事務(wù)里的任何sql查詢結(jié)果需要從對(duì)應(yīng)版本鏈里的最新數(shù)據(jù)開始逐條跟read-view做比對(duì)從而得到最終的快照結(jié)果。

如果是讀已提交隔離級(jí)別Read committed在每次執(zhí)行查詢sql時(shí)都會(huì)重新生成窒舟。

2.1 MVCC

Mysql在可重復(fù)讀隔離級(jí)別下如何保證事務(wù)較高的隔離性,我們上節(jié)課給大家演示過(guò)相恃,同樣的sql查詢語(yǔ)句在一個(gè)事務(wù)里多次執(zhí)行查詢結(jié)果相同辜纲,就算其它事務(wù)對(duì)數(shù)據(jù)有修改也不會(huì)影響當(dāng)前事務(wù)sql語(yǔ)句的查詢結(jié)果。

這個(gè)隔離性就是靠MVCC(Multi-Version Concurrency Control)機(jī)制來(lái)保證的拦耐,對(duì)一行數(shù)據(jù)的讀和寫兩個(gè)操作默認(rèn)是不會(huì)通過(guò)加鎖互斥來(lái)保證隔離性耕腾,避免了頻繁加鎖互斥,而在串行化隔離級(jí)別為了保證較高的隔離性是通過(guò)將所有操作加鎖互斥來(lái)實(shí)現(xiàn)的杀糯。

undo日志版本鏈?zhǔn)侵敢恍袛?shù)據(jù)被多個(gè)事務(wù)依次修改過(guò)后扫俺,在每個(gè)事務(wù)修改完后,Mysql會(huì)保留修改前的數(shù)據(jù)undo回滾日志固翰,并且用兩個(gè)隱藏字段trx_id和roll_pointer把這些undo日志串聯(lián)起來(lái)形成一個(gè)歷史記錄版本鏈狼纬。

版本鏈比對(duì)規(guī)則:

  • 1)如果 row 的 trx_id 落在綠色部分( trx_id<min_id ),表示這個(gè)版本是已提交的事務(wù)生成的骂际,這個(gè)數(shù)據(jù)是可見(jiàn)的疗琉;
  • 2)如果 row 的 trx_id 落在紅色部分( trx_id>max_id ),表示這個(gè)版本是由將來(lái)啟動(dòng)的事務(wù)生成的歉铝,是不可見(jiàn)的(若 row 的 trx_id 就是當(dāng)前自己的事務(wù)是可見(jiàn)的)盈简;
  • 3)如果 row 的 trx_id 落在黃色部分(min_id <=trx_id<= max_id),那就包括兩種情況
    a. 若 row 的 trx_id 在視圖數(shù)組中太示,表示這個(gè)版本是由還沒(méi)提交的事務(wù)生成的柠贤,不可見(jiàn)(若 row 的 trx_id 就是當(dāng)前自己的事務(wù)是可見(jiàn)的);
    b. 若 row 的 trx_id 不在視圖數(shù)組中类缤,表示這個(gè)版本是已經(jīng)提交了的事務(wù)生成的臼勉,可見(jiàn)。

3.鎖機(jī)制

InnoDB使用不同的鎖策略(Locking Strategy)以及MVCC機(jī)制來(lái)實(shí)現(xiàn)不同的隔離級(jí)別餐弱。

  • 讀未提交(Read Uncommitted)
    事務(wù)在讀數(shù)據(jù)的時(shí)候不對(duì)數(shù)據(jù)加鎖宴霸。
    事務(wù)在修改數(shù)據(jù)的時(shí)候只對(duì)數(shù)據(jù)增加行級(jí)共享鎖。
  • 讀已提交(Read Committed)
    普通讀是快照讀膏蚓,這是一種不加鎖的一致性讀猖败,底層使用MVCC實(shí)現(xiàn)。
    加鎖的select, update, delete等語(yǔ)句降允,除了在外鍵約束檢查(foreign-key constraint checking)以及重復(fù)鍵檢查(duplicate-key checking)時(shí)會(huì)封鎖區(qū)間,其他時(shí)刻都只使用記錄鎖艺糜。
  • 可重復(fù)讀(Repeatable Read)
    普通的select使用快照讀剧董。
    加鎖的select(select…in share mode/select…for update)幢尚,update,delete等語(yǔ)句翅楼,它們的鎖尉剩,依賴于它們是否在唯一索引上使用了唯一的查詢條件,或者范圍查詢條件:
    1)在唯一索引上使用唯一的查詢條件毅臊,會(huì)使用記錄鎖,而不會(huì)封鎖記錄之間的間隔,即不會(huì)使用間隙鎖與臨鍵鎖稍走。
    2)范圍查詢條件為非唯一值時(shí)原探,會(huì)使用臨鍵鎖,鎖住索引記錄之間的范圍蚯撩,避免范圍間插入記錄础倍,以避免產(chǎn)生幻讀,以及避免不可重復(fù)讀胎挎。
  • 串行化(Serializable)
    這種事務(wù)隔離級(jí)別下沟启,所有select語(yǔ)句會(huì)被隱式的轉(zhuǎn)化為select…in share mode。
    這會(huì)導(dǎo)致犹菇,如果有未提交的事務(wù)正在修改某些行德迹,所有讀取這些行的操作都會(huì)被阻塞。

3.1 鎖分類

  • 從性能上分為樂(lè)觀鎖(用版本對(duì)比來(lái)實(shí)現(xiàn))和悲觀鎖
  • 從對(duì)數(shù)據(jù)庫(kù)操作的類型分揭芍,分為讀鎖和寫鎖(都屬于悲觀鎖)
    讀鎖(共享鎖胳搞,S鎖(Shared)):針對(duì)同一份數(shù)據(jù),多個(gè)讀操作可以同時(shí)進(jìn)行而不會(huì)互相影響
    寫鎖(排它鎖沼沈,X鎖(eXclusive)):當(dāng)前寫操作沒(méi)有完成前流酬,它會(huì)阻斷其他寫鎖和讀鎖
  • 從對(duì)數(shù)據(jù)操作的粒度分,分為表鎖和行鎖

表鎖:每次操作鎖住整張表列另。開銷小芽腾,加鎖快;不會(huì)出現(xiàn)死鎖页衙;鎖定粒度大摊滔,發(fā)生鎖沖突的概率最高,并發(fā)度最低店乐;一般用在整表數(shù)據(jù)遷移的場(chǎng)景艰躺。

無(wú)索引行鎖會(huì)升級(jí)為表鎖(RR級(jí)別會(huì)升級(jí)為表鎖,RC級(jí)別不會(huì)升級(jí)為表鎖)眨八。

3.2 行鎖

每次操作鎖住一行數(shù)據(jù)腺兴。開銷大,加鎖慢廉侧;會(huì)出現(xiàn)死鎖页响;鎖定粒度最小篓足,發(fā)生鎖沖突的概率最低,并發(fā)度最高闰蚕。

間隙鎖栈拖,鎖的就是兩個(gè)值之間的空隙。間隙鎖是在可重復(fù)讀隔離級(jí)別下才會(huì)生效没陡。

臨鍵鎖(Next-key Locks)是行鎖與間隙鎖的組合涩哟。

3.3 鎖優(yōu)化建議

  • 盡可能讓所有數(shù)據(jù)檢索都通過(guò)索引來(lái)完成,避免無(wú)索引行鎖升級(jí)為表鎖
  • 合理設(shè)計(jì)索引盼玄,盡量縮小鎖的范圍
  • 盡可能減少檢索條件范圍贴彼,避免間隙鎖
  • 盡量控制事務(wù)大小,減少鎖定資源量和時(shí)間長(zhǎng)度强岸,涉及事務(wù)加鎖的sql盡量放在事務(wù)最后執(zhí)行
  • 盡可能低級(jí)別事務(wù)隔離

參考

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末锻弓,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子蝌箍,更是在濱河造成了極大的恐慌青灼,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,470評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件妓盲,死亡現(xiàn)場(chǎng)離奇詭異杂拨,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)悯衬,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門弹沽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人筋粗,你說(shuō)我怎么就攤上這事策橘。” “怎么了娜亿?”我有些...
    開封第一講書人閱讀 162,577評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵丽已,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我买决,道長(zhǎng)沛婴,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,176評(píng)論 1 292
  • 正文 為了忘掉前任督赤,我火速辦了婚禮嘁灯,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘躲舌。我一直安慰自己丑婿,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,189評(píng)論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著羹奉,像睡著了一般毅贮。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上尘奏,一...
    開封第一講書人閱讀 51,155評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音病蛉,去河邊找鬼炫加。 笑死,一個(gè)胖子當(dāng)著我的面吹牛铺然,可吹牛的內(nèi)容都是我干的俗孝。 我是一名探鬼主播,決...
    沈念sama閱讀 40,041評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼魄健,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼赋铝!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起沽瘦,我...
    開封第一講書人閱讀 38,903評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤革骨,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后析恋,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體良哲,經(jīng)...
    沈念sama閱讀 45,319評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,539評(píng)論 2 332
  • 正文 我和宋清朗相戀三年助隧,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了筑凫。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,703評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡并村,死狀恐怖巍实,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情哩牍,我是刑警寧澤棚潦,帶...
    沈念sama閱讀 35,417評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站姐叁,受9級(jí)特大地震影響瓦盛,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜外潜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,013評(píng)論 3 325
  • 文/蒙蒙 一原环、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧处窥,春花似錦嘱吗、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)俄讹。三九已至,卻和暖如春绕德,著一層夾襖步出監(jiān)牢的瞬間患膛,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工耻蛇, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留踪蹬,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,711評(píng)論 2 368
  • 正文 我出身青樓臣咖,卻偏偏與公主長(zhǎng)得像跃捣,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子夺蛇,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,601評(píng)論 2 353

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