《Designing Data-Intensive Applications》第7章 讀書筆記(2):事務(wù)隔離級別與異常

1.說明

如果兩個事務(wù)同時讀寫同一份數(shù)據(jù)茅逮,會引發(fā)并發(fā)競爭問題言缤。
而理論上,隔離性會使得一切變得簡單导而,因為可以讓你認(rèn)為不會有并發(fā)競爭出現(xiàn)
如串行化隔離忱叭,代表db保證事務(wù)執(zhí)行的結(jié)果和他們串行化執(zhí)行的結(jié)果一樣。
但是串行化的代價較高今艺,實際上很多系統(tǒng)會用一些弱化的隔離標(biāo)準(zhǔn)
本節(jié)主要講解

幾種異常:臟讀韵丑,臟寫,Lost update虚缎,幻讀
幾種隔離標(biāo)準(zhǔn):未提交讀(書中沒有展開)撵彻,讀提交,可重復(fù)讀实牡,串行化(下一節(jié)再講)
以及一些實現(xiàn)的講解

2.讀提交

最基本的是讀提交隔離級別陌僵,提供兩個保證

1.讀數(shù)據(jù)是只會讀到已經(jīng)提交的數(shù)據(jù)(沒有臟讀)
2.寫數(shù)據(jù)時,只會覆蓋已經(jīng)提交的寫(沒有臟寫)

臟讀

如果一個事務(wù)的寫還沒有提交创坞,另外一個事務(wù)就讀到了這個未提交的寫數(shù)據(jù)碗短,那么就叫臟讀


圖1,沒有出現(xiàn)臟讀

事務(wù)2不會讀到事務(wù)1未提交的數(shù)據(jù)x=3
解決臟讀的意義

1.避免讀到部分update题涨,如上一節(jié)的圖2
2.如果一個事務(wù)在回滾中偎谁,它之前寫的廢棄掉的數(shù)據(jù)不會被其他事務(wù)讀到

臟寫

兩個事務(wù)同時寫一份數(shù)據(jù)時會發(fā)生什么总滩?
由于不知道明確的順序,常常假定后續(xù)的寫會覆蓋掉前面的寫巡雨。

那么闰渔,如果一個事務(wù)的寫尚未提交,此時另外一個事務(wù)的寫操作來覆蓋這個數(shù)據(jù)铐望,則稱之為臟寫澜建。

讀提交往往通過延遲第二個事務(wù)的寫操作的時間,等到第一個事務(wù)進(jìn)行完了之后再進(jìn)行蝌以,這種方式來避免臟寫炕舵。
臟寫場景如下


圖2,Alice和Bob要買同一個東西跟畅,臟寫導(dǎo)致了最終的買家是Bob咽筋,而發(fā)票卻寄給了Alice。

這里注意一下徊件,上一節(jié)的圖1不叫臟寫奸攻,事務(wù)2的寫在事務(wù)1提交了之后才執(zhí)行。對應(yīng)的問題叫做Lost Updates,下節(jié)會講

實現(xiàn)讀提交

阻止臟寫

常見的阻止臟寫的方式是用行級鎖

事務(wù)要修改一個obj時虱痕,現(xiàn)獲取鎖睹耐,如果獲取成功,那么一直占有鎖知道事務(wù)提交或者回滾
一次只能有一個事務(wù)獲取某個obj的鎖部翘,此時其他事務(wù)都得等到這個鎖釋放了才能重新去獲取

阻止臟讀

當(dāng)然也可以用讀鎖硝训,但是實際表現(xiàn)不佳。因為耗時長的事務(wù)寫操作會導(dǎo)致相關(guān)的只讀事務(wù)等待很長時間新思。

很多db通過類似圖1的方式窖梁,即對于事務(wù)所有寫的記錄,db記錄舊值和新值夹囚。
此時其他事務(wù)來進(jìn)行讀操作時纵刘,返回舊值即可。
僅當(dāng)新值提交了之后才會讀到新值荸哟。

3.快照隔離和可重復(fù)讀

即使在上面讀提交的隔離級別下假哎,還是會有并發(fā)的問題,如下


圖3

圖的意思如下:一開始兩個賬戶各500鞍历,有個Transfer從其中一個賬戶轉(zhuǎn)走100到另外一個賬戶舵抹。但是Alice讀第一個賬戶為500,讀第二個賬戶為400.出現(xiàn)了數(shù)據(jù)不一致的情況堰燎。

這個現(xiàn)象稱為不可重復(fù)讀
如果Alice重新去讀取兩個account掏父,就會發(fā)現(xiàn)一個600(之前是500)一個400笋轨,達(dá)到數(shù)據(jù)一致(一共1000)
在讀提交的隔離級別下秆剪,不可重復(fù)讀是允許的
上面的例子中赊淑,Alice只要重新check一遍就好。但是有些場景不允許這種臨時的不一致,如
1.備份
2.數(shù)據(jù)分析以及一致性檢測

常常通過快照隔離完成,快照隔離就是

每個事務(wù)從一個一致性快照中讀取數(shù)據(jù)仅讽,也就是事務(wù)開始時陶缺,只會看到所有已經(jīng)提交的數(shù)據(jù)。即使有些數(shù)據(jù)會被其他事務(wù)修改洁灵,當(dāng)前書屋也只會看到特定時間點的舊數(shù)據(jù)

快照就是耗時長的只讀統(tǒng)計類事務(wù)如備份以及數(shù)據(jù)分析的福音饱岸。

實現(xiàn)快照隔離

原則:讀事務(wù)與寫事務(wù)互不影響。
這使得db能夠在一致性快照基礎(chǔ)上處理讀事務(wù)的同時徽千,處理寫請求苫费。而不需要讀寫兩個事務(wù)之間有鎖。

為了實現(xiàn)快照隔離双抽,db需要類似圖1中的機(jī)制百框,保留一個obj的新舊版本。來保證不同的事務(wù)能夠看到數(shù)據(jù)不同的狀態(tài)牍汹。這個技術(shù)稱為MVCC(multi version concurrency control)

和讀提交的區(qū)別:
1.幾個版本
讀提交中铐维,obj只用兩個版本即可,已提交版本和覆蓋但未提交的版本(因為有鎖慎菲,不用多個版本)
快照隔離中嫁蛇,用MVCC,是multi version的(因為沒有鎖露该,可能多個事務(wù)同時寫)

2.幾個快照
讀提交中睬棚,一個事務(wù)每次讀都是讀不同的快照(參照圖3理解)
快照隔離中,一個事務(wù)中所有讀都是讀同一個快照

MVCC實現(xiàn)中解幼,每個事務(wù)都要有一個唯一的自增id(txid)闸拿,實現(xiàn)如下圖


MVCC實現(xiàn)快照隔離

注意

上圖每個update行為轉(zhuǎn)化成了一個delete以及一個create.
每條記錄有created_by以及deleted_by字段.
當(dāng)沒有事務(wù)訪問刪除的記錄時,后臺會有g(shù)c進(jìn)程回收deleted_by不為空的記錄

MVCC中每個obj可能有多個版本书幕,那么一個事務(wù)進(jìn)來讀取數(shù)據(jù)的時候新荤,到底是讀取哪個版本呢?
引出下面這個話題

一致性快照的可見性原則

事務(wù)id(txid)來決定哪些obj可見

1.事務(wù)開始前列出當(dāng)前進(jìn)行的(未提交以及丟棄)的事務(wù)id台汇,這些id的提交是不可見的
2.丟棄的事務(wù)苛骨,忽略
3.后續(xù)的事務(wù),忽略
4.所有其他的寫都會被讀到(就相當(dāng)于之前已經(jīng)有的記錄)

換一種方式理解苟呐,一個object對于一個事務(wù)可見痒芝,當(dāng):

1.讀事務(wù)開始時,創(chuàng)建該obj的事務(wù)已經(jīng)提交
2.該obj沒有被刪除牵素,或者說刪除的事務(wù)在讀事務(wù)開始執(zhí)行時還未提交

索引以及快照隔離

如何讓索引也能在MVCC中工作呢严衬?
一種方法是索引指向數(shù)據(jù)的所有版本,由可見性去判斷正確的版本笆呆。
當(dāng)deleted_by不為空的記錄被gc進(jìn)程處理后请琳,index也會相應(yīng)的更新粱挡。

其他的一些方式是B樹上用一些變種(append-only/copy-on-write等),這里不深入展開

快照隔離的命名困惑

快照隔離在不同的db中叫法不一樣俄精,這是因為SQL標(biāo)準(zhǔn)里面询筏,并沒有“快照隔離”這個概念

4.Lost update

圖1的情況中,兩個事務(wù)同時寫一個數(shù)據(jù)時竖慧,出現(xiàn)了類似丟失更新的問題
這個被稱為Lost update嫌套,參照refer中給的一點定義,如下

當(dāng)兩個或多個事務(wù)選擇同一行圾旨,然后基于最初選定的值更新該行時踱讨,由于每個事務(wù)都不知道其他事務(wù)的存在,就會發(fā)生丟失更新問題

一般解決方式如下砍的,不展開:

原子寫操作
顯式用鎖(for update語句)
CAS操作

不過在分布式系統(tǒng)中勇蝙,并發(fā)的寫沖突可能往往靠應(yīng)用程序自己解決,這個請看前面的相關(guān)章節(jié).

5.幻讀

除了上面的競爭外挨约,還有其他并發(fā)寫可能會出現(xiàn)的競爭味混,如下
醫(yī)院在任何時候必須至少有一位醫(yī)生在值班。醫(yī)生可以調(diào)整他們的輪班诫惭,前提是至少有一個同事在醫(yī)院值班翁锡。Alice和Bob是兩位今天值班的醫(yī)生。兩人都想調(diào)整輪班夕土,不幸的是馆衔,他們碰巧點擊按鈕大約在同一時間取消輪班。接下來發(fā)生的情況如圖所示:


幻讀

這個問題既不是臟寫又不是lost updates怨绣,因為兩個事物在update兩個不同的obj(Alice和Bob各自的值班表)角溃。這個問題不明顯,但毫無疑問是競爭篮撑,因為如果串行化執(zhí)行就不會有這個問題了减细。

參照之前解決lost updates的方法,解決幻讀則需要

1.單obj的原子操作不管用了赢笨,需要多obj的原子操作
2.需要串行化的隔離級別(后續(xù)再講)
3.有些db可以配置約束未蝌,自行選擇觸發(fā)器或者視圖相關(guān)
4.select for update鎖住多行

幻讀的發(fā)生,都會有特定的形式茧妒,這里不用書中給的定義萧吠,用refer中的博客提到的感覺說的更好

幻讀發(fā)生在正在執(zhí)行的事務(wù) T1 有斷言的讀 (select where) 時,另外一個事務(wù) T2 執(zhí)行了和斷言集合有交集的插入操作桐筏。

6.總結(jié)

這一節(jié)講了幾種異常

臟讀纸型,臟寫
Lost updates
幻讀

對應(yīng)幾種解決的隔離級別

未提交讀
提交讀
可重復(fù)讀

這一節(jié)沒有講串行化,篇幅原因,下一節(jié)再講
幾個隔離級別的翻譯是參照網(wǎng)絡(luò)上的定義

參照refer中 https://zhuanlan.zhihu.com/p/29166694
對應(yīng)關(guān)系如下

各具體數(shù)據(jù)庫并不一定完全實現(xiàn)了上述 4 個隔離級別

7.思考

讀提交和可重復(fù)讀的區(qū)別
實現(xiàn)快照隔離中 講解過

MVCC多個版本中狰腌,一個事務(wù)讀取時該選擇哪個版本

參照上述 可見性原則

Lost Update
按照refer中除破,這個似乎用鎖避免并發(fā)寫就可以(http://blog.csdn.net/bluishglc/article/details/5626009),也就是未提交讀的隔離級別就能解決的癌别。
因此感覺文章順序有點問題,這里應(yīng)該放在最前面蹋笼,而且注意 Lost update不是隔離級別展姐,只是一個并發(fā)考慮的問題

Lost update與臟寫的區(qū)別
能保證不出現(xiàn)臟寫的隔離級別,不一定保證不會出現(xiàn)Lost update
Lost update的情形中剖毯,兩個事務(wù)都沒有看到對方未commit的數(shù)據(jù)(臟寫是看得到的)

個人感受
不同的情形可能都需要深挖圾笨,書籍也有沒有完全的深入講解,點到即止逊谋。
自己知道這些東西就好

8.名詞

隔離標(biāo)準(zhǔn)
讀提交
臟讀桂躏,臟寫
(不)可重復(fù)讀
快照隔離
MVCC(multi version concurrency control)
lost updates
幻讀

9.refer

http://www.reibang.com/p/a84e4f41a2aa

lost update相關(guān)
http://blog.csdn.net/bluishglc/article/details/5626009
https://zhuanlan.zhihu.com/p/29166694

幻讀
這篇博客寫的太厲害了 https://ggaaooppeenngg.github.io/zh-CN/2017/04/16/SQL%E9%9A%94%E7%A6%BB%E7%BA%A7%E5%88%AB/

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末申窘,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌萄焦,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,539評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件崩侠,死亡現(xiàn)場離奇詭異费薄,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)部宿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評論 3 396
  • 文/潘曉璐 我一進(jìn)店門抄腔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人理张,你說我怎么就攤上這事赫蛇。” “怎么了雾叭?”我有些...
    開封第一講書人閱讀 165,871評論 0 356
  • 文/不壞的土叔 我叫張陵悟耘,是天一觀的道長。 經(jīng)常有香客問我织狐,道長作煌,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,963評論 1 295
  • 正文 為了忘掉前任赚瘦,我火速辦了婚禮粟誓,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘起意。我一直安慰自己鹰服,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,984評論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著悲酷,像睡著了一般套菜。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上设易,一...
    開封第一講書人閱讀 51,763評論 1 307
  • 那天逗柴,我揣著相機(jī)與錄音,去河邊找鬼顿肺。 笑死戏溺,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的屠尊。 我是一名探鬼主播旷祸,決...
    沈念sama閱讀 40,468評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼讼昆!你這毒婦竟也來了托享?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤浸赫,失蹤者是張志新(化名)和其女友劉穎闰围,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體既峡,經(jīng)...
    沈念sama閱讀 45,850評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡辫诅,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,002評論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了涧狮。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片炕矮。...
    茶點故事閱讀 40,144評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖者冤,靈堂內(nèi)的尸體忽然破棺而出肤视,到底是詐尸還是另有隱情,我是刑警寧澤涉枫,帶...
    沈念sama閱讀 35,823評論 5 346
  • 正文 年R本政府宣布邢滑,位于F島的核電站,受9級特大地震影響愿汰,放射性物質(zhì)發(fā)生泄漏困后。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,483評論 3 331
  • 文/蒙蒙 一衬廷、第九天 我趴在偏房一處隱蔽的房頂上張望摇予。 院中可真熱鬧,春花似錦吗跋、人聲如沸侧戴。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽酗宋。三九已至积仗,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間蜕猫,已是汗流浹背寂曹。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留回右,地道東北人隆圆。 一個月前我還...
    沈念sama閱讀 48,415評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像楣黍,于是被迫代替她去往敵國和親匾灶。 傳聞我的和親對象是個殘疾皇子棱烂,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,092評論 2 355

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