面試官問你:MySQL事務(wù)和隔離級別,該如何回答

一流昏、事務(wù)

事務(wù)是由一組SQL語句組成的邏輯處理單元但两,是滿足 ACID 特性的一組操作鬓梅,可以通過 Commit 提交一個(gè)事務(wù),也可以使用 Rollback 進(jìn)行回滾谨湘。事務(wù)具有以下4個(gè)屬性绽快,通常簡稱為事務(wù)的ACID屬性:

  • 原子性(Atomicity):事務(wù)是一個(gè)原子操作單元,其對數(shù)據(jù)的修改紧阔,要么全都執(zhí)行坊罢,要么全都不執(zhí)行。比如在同一個(gè)事務(wù)中的SQL語句擅耽,要么全部執(zhí)行成功活孩,要么全部執(zhí)行失敗」猿穑回滾可以用日志來實(shí)現(xiàn)诱鞠,日志記錄著事務(wù)所執(zhí)行的修改操作挎挖,在回滾時(shí)反向執(zhí)行這些修改操作即可。
  • 一致性(Consistent):在事務(wù)開始和完成時(shí)航夺,數(shù)據(jù)都必須保持一致狀態(tài)蕉朵。這意味著所有相關(guān)的數(shù)據(jù)規(guī)則都必須應(yīng)用于事務(wù)的修改,以保持?jǐn)?shù)據(jù)的完整性阳掐;事務(wù)結(jié)束時(shí)始衅,所有的內(nèi)部數(shù)據(jù)結(jié)構(gòu)(如B樹索引或雙向鏈表)也都必須是正確的。 以轉(zhuǎn)賬為例子缭保,A向B轉(zhuǎn)賬汛闸,假設(shè)轉(zhuǎn)賬之前這兩個(gè)用戶的錢加起來總共是2000,那么A向B轉(zhuǎn)賬之后艺骂,不管這兩個(gè)賬戶怎么轉(zhuǎn)诸老,A用戶的錢和B用戶的錢加起來的總額還是2000,這個(gè)就是事務(wù)的一致性钳恕。
  • 隔離性(Isolation):數(shù)據(jù)庫系統(tǒng)提供一定的隔離機(jī)制别伏,保證事務(wù)在不受外部并發(fā)操作影響的“獨(dú)立”環(huán)境執(zhí)行。 隔離性是當(dāng)多個(gè)用戶并發(fā)訪問數(shù)據(jù)庫時(shí)忧额,比如操作同一張表時(shí)厘肮,數(shù)據(jù)庫為每一個(gè)用戶開啟的事務(wù),不能被其他事務(wù)的操作所干擾睦番,多個(gè)并發(fā)事務(wù)之間要相互隔離类茂。即要達(dá)到這么一種效果:對于任意兩個(gè)并發(fā)的事務(wù) T1 和 T2,在事務(wù) T1 看來托嚣,T2 要么在 T1 開始之前就已經(jīng)結(jié)束巩检,要么在 T1 結(jié)束之后才開始,這樣每個(gè)事務(wù)都感覺不到有其他事務(wù)在并發(fā)地執(zhí)行示启。
  • 持久性(Durable):事務(wù)完成之后碴巾,它對于數(shù)據(jù)的修改是永久性的,即使出現(xiàn)系統(tǒng)故障也能夠保持丑搔。  可以通過數(shù)據(jù)庫備份和恢復(fù)來實(shí)現(xiàn)厦瓢,在系統(tǒng)發(fā)生奔潰時(shí),使用備份的數(shù)據(jù)庫進(jìn)行數(shù)據(jù)恢復(fù)啤月。

MySQL 默認(rèn)采用自動提交模式煮仇。也就是說,如果不顯式使用 START TRANSACTION 語句來開始一個(gè)事務(wù)谎仲,那么每個(gè)查詢都會被當(dāng)做一個(gè)事務(wù)自動提交浙垫。

這幾個(gè)特性不是一種平級關(guān)系

  • 只有滿足一致性,事務(wù)的執(zhí)行結(jié)果才是正確的。
  • 在無并發(fā)的情況下夹姥,事務(wù)串行執(zhí)行杉武,隔離性一定能夠滿足。此時(shí)要只要能滿足原子性辙售,就一定能滿足一致性轻抱。
  • 在并發(fā)的情況下,多個(gè)事務(wù)并發(fā)執(zhí)行旦部,事務(wù)不僅要滿足原子性祈搜,還需要滿足隔離性,才能滿足一致性士八。
  • 事務(wù)滿足持久化是為了能應(yīng)對數(shù)據(jù)庫奔潰的情況容燕。

二、并發(fā)一致性問題

Ⅰ婚度、更新丟失(Lost Update)

T1 和 T2 兩個(gè)事務(wù)都對一個(gè)數(shù)據(jù)進(jìn)行修改蘸秘,T1 先修改,T2 隨后修改蝗茁,T2 的修改覆蓋了 T1 的修改醋虏。

例如,兩個(gè)程序員修改同一java文件评甜。每程序員獨(dú)立地更改其副本,然后保存更改后的副本仔涩,這樣就覆蓋了原始文檔忍坷。最后保存其更改副本的編輯人員覆蓋前一個(gè)程序員所做的更改。

如果在一個(gè)程序員完成并提交事務(wù)之前熔脂,另一個(gè)程序員不能訪問同一文件佩研,則可避免此問題

Ⅱ霞揉、臟讀

一句話:事務(wù)B讀取到了事務(wù)A已修改但尚未提交的的數(shù)據(jù)旬薯,還在這個(gè)數(shù)據(jù)基礎(chǔ)上做了操作。此時(shí)适秩,如果A事務(wù)回滾Rollback绊序,B讀取的數(shù)據(jù)無效,不符合一致性要求秽荞。

解決辦法: 把數(shù)據(jù)庫的事務(wù)隔離級別調(diào)整到 READ_COMMITTED

T1 修改一個(gè)數(shù)據(jù)骤公,T2 隨后讀取這個(gè)數(shù)據(jù)。如果 T1 撤銷了這次修改扬跋,那么 T2 讀取的數(shù)據(jù)是臟數(shù)據(jù)阶捆。

Ⅲ、不可重復(fù)讀(Non-Repeatable Reads)

在一個(gè)事務(wù)內(nèi),多次讀同一個(gè)數(shù)據(jù)洒试。在這個(gè)事務(wù)還沒有結(jié)束時(shí)倍奢,另一個(gè)事務(wù)也訪問該同一數(shù)據(jù)。那么垒棋,在第一個(gè)事務(wù)的兩次讀數(shù)據(jù)之間卒煞。由于第二個(gè)事務(wù)的修改,那么第一個(gè)事務(wù)讀到的數(shù)據(jù)可能不一樣捕犬,這樣就發(fā)生了在一個(gè)事務(wù)內(nèi)兩次讀到的數(shù)據(jù)是不一樣的跷坝,因此稱為不可重復(fù)讀,即原始讀取不可重復(fù)碉碉。

一句話:一個(gè)事務(wù)范圍內(nèi)兩個(gè)相同的查詢卻返回了不同數(shù)據(jù)柴钻。

同時(shí)操作,事務(wù)1分別讀取事務(wù)2操作時(shí)和提交后的數(shù)據(jù)垢粮,讀取的記錄內(nèi)容不一致贴届。不可重復(fù)讀是指在同一個(gè)事務(wù)內(nèi),兩個(gè)相同的查詢返回了不同的結(jié)果蜡吧。

解決辦法: 如果只有在修改事務(wù)完全提交之后才可以讀取數(shù)據(jù)毫蚓,則可以避免該問題。把數(shù)據(jù)庫的事務(wù)隔離級別調(diào)整到REPEATABLE_READ

T2 讀取一個(gè)數(shù)據(jù)昔善,T1 對該數(shù)據(jù)做了修改元潘。如果 T2 再次讀取這個(gè)數(shù)據(jù),此時(shí)讀取的結(jié)果和第一次讀取的結(jié)果不同君仆。

Ⅳ翩概、幻讀

一個(gè)事務(wù)T1按相同的查詢條件重新讀取以前檢索過的數(shù)據(jù),卻發(fā)現(xiàn)其他事務(wù)T2插入了滿足其查詢條件的新數(shù)據(jù)返咱,這種現(xiàn)象就稱為“幻讀”钥庇。(和可重復(fù)讀類似,但是事務(wù) T2 的數(shù)據(jù)操作僅僅是插入和刪除咖摹,不是修改數(shù)據(jù)评姨,讀取的記錄數(shù)量前后不一致)

一句話:事務(wù)A 讀取到了事務(wù)B提交的新增數(shù)據(jù),不符合隔離性萤晴。

解決辦法: 如果在操作事務(wù)完成數(shù)據(jù)處理之前吐句,任何其他事務(wù)都不可以添加新數(shù)據(jù),則可避免該問題店读。把數(shù)據(jù)庫的事務(wù)隔離級別調(diào)整到 SERIALIZABLE_READ蕴侧。

T1 讀取某個(gè)范圍的數(shù)據(jù),T2 在這個(gè)范圍內(nèi)插入新的數(shù)據(jù)两入,T1 再次讀取這個(gè)范圍的數(shù)據(jù)净宵,此時(shí)讀取的結(jié)果和和第一次讀取的結(jié)果不同

三、事務(wù)隔離級別

"臟讀"择葡、"不可重復(fù)讀"和"幻讀"紧武,其實(shí)都是數(shù)據(jù)庫讀一致性問題,必須由數(shù)據(jù)庫提供一定的事務(wù)隔離機(jī)制來解決敏储。

數(shù)據(jù)庫的事務(wù)隔離越嚴(yán)格阻星,并發(fā)副作用越小,但付出的代價(jià)也就越大已添,因?yàn)槭聞?wù)隔離實(shí)質(zhì)上就是使事務(wù)在一定程度上 “串行化”進(jìn)行妥箕,這顯然與“并發(fā)”是矛盾的。同時(shí)更舞,不同的應(yīng)用對讀一致性和事務(wù)隔離程度的要求也是不同的畦幢,比如許多應(yīng)用對“不可重復(fù)讀”和“幻讀”并不敏感,可能更關(guān)心數(shù)據(jù)并發(fā)訪問的能力缆蝉。

MYSQL秤畲校看當(dāng)前數(shù)據(jù)庫的事務(wù)隔離級別:show variables like 'tx_isolation';

Ⅰ、讀未提交 (Read Uncommitted)

最低的隔離等級刊头,允許其他事務(wù)看到?jīng)]有提交的數(shù)據(jù)黍瞧,會導(dǎo)致臟讀。

Ⅱ原杂、讀已提交 (Read Committed)

被讀取的數(shù)據(jù)可以被其他事務(wù)修改印颤,這樣可能導(dǎo)致不可重復(fù)讀。也就是說穿肄,事務(wù)讀取的時(shí)候獲取讀鎖年局,但是在讀完之后立即釋放(不需要等事務(wù)結(jié)束),而寫鎖則是事務(wù)提交之后才釋放被碗,釋放讀鎖之后某宪,就可能被其他事務(wù)修改數(shù)據(jù)仿村。該等級也是 SQL Server 默認(rèn)的隔離等級锐朴。

Ⅲ、可重復(fù)讀(Repeatable Read)

所有被 Select 獲取的數(shù)據(jù)都不能被修改蔼囊,這樣就可以避免一個(gè)事務(wù)前后讀取數(shù)據(jù)不一致的情況焚志。但是卻沒有辦法控制幻讀,因?yàn)檫@個(gè)時(shí)候其他事務(wù)不能更改所選的數(shù)據(jù)畏鼓,但是可以增加數(shù)據(jù)酱酬,即前一個(gè)事務(wù)有讀鎖但是沒有范圍鎖,為什么叫做可重復(fù)讀等級呢云矫?那是因?yàn)樵摰燃壗鉀Q了下面的不可重復(fù)讀問題膳沽。(引申:現(xiàn)在主流數(shù)據(jù)庫都使用 MVCC 并發(fā)控制,使用之后RR(可重復(fù)讀)隔離級別下是不會出現(xiàn)幻讀的現(xiàn)象。)

MYSQL默認(rèn)是REPEATABLE-READ 挑社。

Ⅳ陨界、串行化(Serializable)

所有事務(wù)一個(gè)接著一個(gè)的執(zhí)行,這樣可以避免幻讀 (phantom read)痛阻,對于基于鎖來實(shí)現(xiàn)并發(fā)控制的數(shù)據(jù)庫來說菌瘪,串行化要求在執(zhí)行范圍查詢的時(shí)候,需要獲取范圍鎖阱当,如果不是基于鎖實(shí)現(xiàn)并發(fā)控制的數(shù)據(jù)庫俏扩,則檢查到有違反串行操作的事務(wù)時(shí),需回滾該事務(wù)弊添。

Ⅴ录淡、總結(jié)

  • 讀未提交: 一個(gè)事務(wù)還沒提交時(shí),它做的變更就能被別的事務(wù)看到表箭。
  • 讀提交: 一個(gè)事務(wù)提交之后赁咙,它做的變更才會被其他事務(wù)看到。
  • 可重復(fù)讀 : 一個(gè)事務(wù)執(zhí)行過程中看到的數(shù)據(jù)免钻,總是跟這個(gè)事務(wù)在啟動時(shí)看到的數(shù)據(jù)是一致的彼水。當(dāng)然在可重復(fù)讀隔離級別下,未提交變更對其他事務(wù)也是不可見的极舔。
  • 串行化: 顧名思義是對于同一行記錄凤覆,“寫”會加“寫鎖”,“讀”會加“讀鎖”拆魏。當(dāng)出現(xiàn)讀寫鎖沖突的時(shí)候盯桦,后訪問的事務(wù)必須等前一個(gè)事務(wù)執(zhí)行完成,才能繼續(xù)執(zhí)行渤刃。

四個(gè)級別逐漸增強(qiáng)拥峦,每個(gè)級別解決一個(gè)問題,事務(wù)級別越高卖子,性能越差略号,大多數(shù)環(huán)境(Read committed 就可以用了)

隔離級別 讀數(shù)據(jù)一致性 臟讀 不可重復(fù)讀 幻影讀
未提交讀 最低級別
提交讀 語句級 ×
可重復(fù)讀 事務(wù)級 × ×
可串行讀 最高級別,事務(wù)級 × × ×

寫在最后

  • 第一:看完點(diǎn)贊,感謝您對作者的認(rèn)可洋闽;
  • ...
  • 第二:隨手轉(zhuǎn)發(fā)玄柠,分享知識,讓更多人學(xué)習(xí)到诫舅;
  • ...
  • 第三:記得點(diǎn)關(guān)注羽利,每天更新的!?浮这弧!
  • ...
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末娃闲,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子匾浪,更是在濱河造成了極大的恐慌畜吊,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,884評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件户矢,死亡現(xiàn)場離奇詭異玲献,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)梯浪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,755評論 3 385
  • 文/潘曉璐 我一進(jìn)店門捌年,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人挂洛,你說我怎么就攤上這事礼预。” “怎么了虏劲?”我有些...
    開封第一講書人閱讀 158,369評論 0 348
  • 文/不壞的土叔 我叫張陵托酸,是天一觀的道長。 經(jīng)常有香客問我柒巫,道長励堡,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,799評論 1 285
  • 正文 為了忘掉前任堡掏,我火速辦了婚禮应结,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘泉唁。我一直安慰自己鹅龄,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,910評論 6 386
  • 文/花漫 我一把揭開白布亭畜。 她就那樣靜靜地躺著扮休,像睡著了一般。 火紅的嫁衣襯著肌膚如雪拴鸵。 梳的紋絲不亂的頭發(fā)上玷坠,一...
    開封第一講書人閱讀 50,096評論 1 291
  • 那天,我揣著相機(jī)與錄音宝踪,去河邊找鬼侨糟。 笑死碍扔,一個(gè)胖子當(dāng)著我的面吹牛瘩燥,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播不同,決...
    沈念sama閱讀 39,159評論 3 411
  • 文/蒼蘭香墨 我猛地睜開眼厉膀,長吁一口氣:“原來是場噩夢啊……” “哼溶耘!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起服鹅,我...
    開封第一講書人閱讀 37,917評論 0 268
  • 序言:老撾萬榮一對情侶失蹤凳兵,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后企软,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體庐扫,經(jīng)...
    沈念sama閱讀 44,360評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,673評論 2 327
  • 正文 我和宋清朗相戀三年仗哨,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了形庭。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,814評論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡厌漂,死狀恐怖萨醒,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情苇倡,我是刑警寧澤富纸,帶...
    沈念sama閱讀 34,509評論 4 334
  • 正文 年R本政府宣布,位于F島的核電站旨椒,受9級特大地震影響晓褪,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜综慎,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,156評論 3 317
  • 文/蒙蒙 一辞州、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧寥粹,春花似錦变过、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至阔拳,卻和暖如春崭孤,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背糊肠。 一陣腳步聲響...
    開封第一講書人閱讀 32,123評論 1 267
  • 我被黑心中介騙來泰國打工辨宠, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人货裹。 一個(gè)月前我還...
    沈念sama閱讀 46,641評論 2 362
  • 正文 我出身青樓嗤形,卻偏偏與公主長得像,于是被迫代替她去往敵國和親弧圆。 傳聞我的和親對象是個(gè)殘疾皇子赋兵,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,728評論 2 351