Spring和Mybatis架構(gòu)重現(xiàn)臟讀,不可重復(fù)讀和幻讀

隔離(數(shù)據(jù)庫(kù)系統(tǒng))

在數(shù)據(jù)庫(kù)系統(tǒng)中执隧,隔離決定了其他用戶和系統(tǒng)如何看到事務(wù)完整性。 例如户侥,當(dāng)用戶創(chuàng)建采購(gòu)訂單并創(chuàng)建了表頭但未創(chuàng)建采購(gòu)訂單行時(shí)镀琉,表頭對(duì)其他系統(tǒng)/用戶是否可見(jiàn)(執(zhí)行并行操作,如采購(gòu)訂單報(bào)告)蕊唐?

較低的隔離級(jí)別會(huì)增加許多用戶同時(shí)訪問(wèn)相同數(shù)據(jù)的能力屋摔,但會(huì)增加用戶可能遇到的并發(fā)影響(如臟讀或丟失更新)的數(shù)量。 相反替梨,更高的隔離級(jí)別減少了用戶可能遇到的并發(fā)影響的種類钓试,但需要更多的系統(tǒng)資源装黑,并增加了一個(gè)事務(wù)阻塞另一個(gè)事務(wù)的可能性。

隔離通常在數(shù)據(jù)庫(kù)級(jí)別定義為一個(gè)屬性弓熏,該屬性定義一個(gè)操作所做的更改如何/何時(shí)對(duì)其他操作可見(jiàn)恋谭。 在較舊的系統(tǒng)上,它可以通過(guò)系統(tǒng)實(shí)現(xiàn)挽鞠,例如通過(guò)使用臨時(shí)表箕别。 在兩層系統(tǒng)中,需要事務(wù)處理(TP)管理器來(lái)維護(hù)隔離滞谢。 在n層系統(tǒng)(例如試圖預(yù)訂航班最后一個(gè)座位的多個(gè)網(wǎng)站)中串稀,需要結(jié)合使用存儲(chǔ)過(guò)程和交易管理來(lái)完成預(yù)訂并向客戶發(fā)送確認(rèn)。

當(dāng)一個(gè)事務(wù)被允許從一個(gè)被另一個(gè)正在運(yùn)行的事務(wù)修改但尚未提交的行讀取數(shù)據(jù)時(shí)狮杨,發(fā)生臟讀(又名未提交依賴)母截。

隔離是ACID(Atomicity 原子性, Consistency 一致性, Isolation 隔離, Durability 耐久性)的屬性之一。

并發(fā)控制

并發(fā)控制包含DBMS中處理隔離并保證相關(guān)正確性的基本機(jī)制橄教。數(shù)據(jù)庫(kù)和存儲(chǔ)引擎(見(jiàn)上文)大量使用它來(lái)保證并發(fā)事務(wù)的正確執(zhí)行清寇,以及(不同的機(jī)制)其他DBMS進(jìn)程的正確性。與事務(wù)相關(guān)的機(jī)制通常根據(jù)數(shù)據(jù)庫(kù)數(shù)據(jù)訪問(wèn)操作時(shí)間(事務(wù)調(diào)度)將命令分類為以可串行性和可恢復(fù)性為特征的調(diào)度屬性护蝶。限制數(shù)據(jù)庫(kù)訪問(wèn)操作執(zhí)行通常意味著性能(執(zhí)行率)降低华烟,因此并發(fā)控制機(jī)制通常被設(shè)計(jì)為在約束下提供盡可能最佳的性能。通常持灰,如果可能的話盔夜,在不損害正確性的情況下,可串行性屬性會(huì)受到制約以獲得更好的性能堤魁。但是喂链,可恢復(fù)性不會(huì)受到制約,因?yàn)檫@通常會(huì)違反數(shù)據(jù)庫(kù)完整性約束妥泉。

兩階段鎖定是DBMS中最常見(jiàn)的事務(wù)并發(fā)控制方法椭微,用于為數(shù)據(jù)庫(kù)訪問(wèn)的正確性提供可串行性和可恢復(fù)性。為了訪問(wèn)數(shù)據(jù)庫(kù)對(duì)象盲链,事務(wù)首先需要獲取該對(duì)象的鎖贴彼。根據(jù)訪問(wèn)操作類型(例如讀取或?qū)懭雽?duì)象)和鎖定類型浊闪,如果另一個(gè)事務(wù)正在為該對(duì)象持有鎖定蓬蝶,則可能會(huì)阻止并推遲獲取該鎖定峭跳。

隔離級(jí)別

在DBMS(數(shù)據(jù)庫(kù)管理系統(tǒng))中的四個(gè)ACID屬性中,隔離屬性是最經(jīng)常放松的屬性悠轩。當(dāng)試圖保持最高級(jí)別的隔離時(shí)间狂,DBMS通常會(huì)獲取可能導(dǎo)致并發(fā)性丟失或?qū)崿F(xiàn)多版本并發(fā)控制的數(shù)據(jù)鎖定。這需要為應(yīng)用程序添加邏輯才能正常運(yùn)行火架。

大多數(shù)DBMS提供了許多事務(wù)隔離級(jí)別鉴象,它們控制選擇數(shù)據(jù)時(shí)發(fā)生的鎖定程度忙菠。對(duì)于許多數(shù)據(jù)庫(kù)應(yīng)用程序,可以構(gòu)造大多數(shù)數(shù)據(jù)庫(kù)事務(wù)以避免需要高隔離級(jí)別(例如SERIALIZABLE級(jí)別)纺弊,從而減少系統(tǒng)的鎖定開(kāi)銷牛欢。程序員必須仔細(xì)分析數(shù)據(jù)庫(kù)訪問(wèn)代碼,以確保放松隔離不會(huì)導(dǎo)致難以發(fā)現(xiàn)的軟件錯(cuò)誤淆游。相反傍睹,如果使用更高的隔離級(jí)別,則會(huì)增加死鎖的可能性犹菱,這也需要仔細(xì)分析和編程技術(shù)來(lái)避免拾稳。

Serializable

這是最高的隔離級(jí)別。

使用基于鎖的并發(fā)控制DBMS實(shí)現(xiàn)時(shí)腊脱,可序列化要求在事務(wù)結(jié)束時(shí)釋放讀取和寫入鎖(在選定數(shù)據(jù)上獲确玫谩)。當(dāng)SELECT查詢使用范圍WHERE子句時(shí)陕凹,還必須獲取范圍鎖悍抑,特別是為了避免幻像讀取現(xiàn)象。

使用基于非鎖定的并發(fā)控制時(shí)杜耙,不會(huì)獲取鎖定;但是搜骡,如果系統(tǒng)在幾個(gè)并發(fā)事務(wù)中檢測(cè)到寫沖突,則只允許其中一個(gè)事務(wù)提交佑女。有關(guān)此主題的更多詳細(xì)信息记靡,請(qǐng)參閱快照隔離

來(lái)自:(第二份非正式評(píng)審草案)ISO / IEC 9075:1992,數(shù)據(jù)庫(kù)語(yǔ)言SQL- 1992年7月30日:在隔離級(jí)別SERIALIZABLE下執(zhí)行并發(fā)SQL事務(wù)保證可序列化珊豹◆こ剩可序列化的執(zhí)行被定義為執(zhí)行并發(fā)執(zhí)行的SQL事務(wù)的操作榕订,這些操作產(chǎn)生與那些相同的SQL事務(wù)的一些串行執(zhí)行相同的效果店茶。串行執(zhí)行是每個(gè)SQL事務(wù)在下一個(gè)SQL事務(wù)開(kāi)始之前執(zhí)行完成的一次執(zhí)行。

Repeatable reads

在此隔離級(jí)別中劫恒,基于鎖的并發(fā)控制DBMS實(shí)現(xiàn)會(huì)保持讀取和寫入鎖定(在選定數(shù)據(jù)上獲确坊谩)直到事務(wù)結(jié)束。但是两嘴,范圍鎖不受管理丛楚,因此可能發(fā)生幻像讀取。

在這個(gè)隔離級(jí)別寫偏序是可能的憔辫,寫偏序——Write Skew趣些,是一種由于允許兩個(gè)不同的寫入器(先前讀取它們正在更新的列)寫入到同一表中的同一列,導(dǎo)致列的數(shù)據(jù)是這兩個(gè)事務(wù)的混合贰您。其根本的原因是由于每個(gè)事務(wù)在更新過(guò)程中無(wú)法看到其他事務(wù)的更改的結(jié)果坏平,導(dǎo)致各個(gè)事務(wù)提交之后的最終結(jié)果違反了一致性拢操。

Read committed

在這個(gè)隔離級(jí)別中,基于鎖的并發(fā)控制DBMS實(shí)現(xiàn)會(huì)保持寫鎖(在選定數(shù)據(jù)上獲炔疤妗)直到事務(wù)結(jié)束令境,但是只要SELECT操作被執(zhí)行,讀鎖就會(huì)被釋放(所以不可重復(fù)讀取現(xiàn)象可以發(fā)生在這個(gè)隔離級(jí)別)顾瞪。與前一級(jí)一樣舔庶,范圍鎖不受管理。

簡(jiǎn)單來(lái)說(shuō)陈醒,read committed是一個(gè)隔離級(jí)別惕橙,它保證讀取數(shù)據(jù)時(shí)讀取的任何數(shù)據(jù)都被提交。它只是限制讀者看到任何中間的钉跷,未提交的吕漂,“臟”的閱讀。它不會(huì)承諾如果事務(wù)重新發(fā)布讀取尘应,它會(huì)找到相同的數(shù)據(jù)惶凝;數(shù)據(jù)讀取后可以自由更改。

Read uncommitted

這是最低的隔離級(jí)別犬钢。在這個(gè)級(jí)別中苍鲜,允許臟讀,因此一個(gè)事務(wù)可能會(huì)看到其他事務(wù)未做出的更改玷犹。

由于每個(gè)隔離級(jí)別都比下面更強(qiáng)混滔,因?yàn)闆](méi)有更高的隔離級(jí)別允許較低級(jí)別禁止的操作,該標(biāo)準(zhǔn)允許DBMS以比所請(qǐng)求的更高的隔離級(jí)別運(yùn)行事務(wù)(例如歹颓,“讀取已提交”事務(wù)實(shí)際上可以在“可重復(fù)讀”隔離級(jí)別執(zhí)行)坯屿。

讀取現(xiàn)象

當(dāng)事務(wù)1讀取事務(wù)2可能已經(jīng)改變的數(shù)據(jù)時(shí),ANSI / ISO標(biāo)準(zhǔn)SQL 92引用三種不同的讀取現(xiàn)象巍扛。

臟讀

臟讀(又名未提交依賴)發(fā)生在當(dāng)事務(wù)允許從某行讀取數(shù)據(jù)领跛,但該行正在被其他事務(wù)修改并且未提交的時(shí)候。

臟讀的工作方式與不可重復(fù)讀取類似; 但是撤奸,第二個(gè)事務(wù)不需要為第一個(gè)查詢返回不同的結(jié)果吠昭。 READ UNCOMMITTED隔離級(jí)別中可能阻止的唯一事情是更新在結(jié)果中出現(xiàn)亂序; 也就是說(shuō),前面的更新將始終在后面更新之前出現(xiàn)在結(jié)果集中胧瓜。

臟讀sql

在我們的示例中矢棚,事務(wù)2會(huì)更改一行,但不會(huì)提交更改府喳。 事務(wù)1然后讀取未提交的數(shù)據(jù)蒲肋。 現(xiàn)在,如果事務(wù)2回滾其更改(已由事務(wù)1讀取)或更新對(duì)數(shù)據(jù)庫(kù)的不同更改兜粘,則數(shù)據(jù)視圖在事務(wù)1的記錄中可能是錯(cuò)誤的强胰。

重現(xiàn)步驟:

1. 設(shè)置propagation="REQUIRED" isolation="READ_UNCOMMITTED";

2. 執(zhí)行查詢記錄1妹沙,Thread.sleep(3000)偶洋;

3. 在事務(wù)1休眠期間,執(zhí)行事務(wù)2更新記錄1距糖;

4. 再次執(zhí)行查詢記錄1玄窝;

5. 事務(wù)2拋出異常,發(fā)生回滾悍引;

兩次結(jié)果不一致恩脂,發(fā)生臟讀。若改為isolation="READ_COMMITTED"趣斤,兩次結(jié)果一致俩块。

不可重復(fù)的讀

發(fā)生不可重復(fù)讀取時(shí),在事務(wù)過(guò)程中浓领,行被檢索兩次玉凯,行之間的值在讀取之間不同。

當(dāng)執(zhí)行SELECT時(shí)未獲取讀取鎖定時(shí)联贩,或者在執(zhí)行SELECT操作時(shí)立即釋放獲取的受影響行上的鎖定時(shí)漫仆,基于鎖定的并發(fā)控制方法中可能出現(xiàn)不可重復(fù)讀取現(xiàn)象。 在多版本并發(fā)控制方法下泪幌,當(dāng)由提交沖突影響的事務(wù)必須回滾的要求放寬時(shí)盲厌,可能發(fā)生不可重復(fù)讀取。

不可重復(fù)讀sql

重現(xiàn)步驟:

1. 設(shè)置propagation="REQUIRED" isolation="READ_COMMITTED"祸泪;

2. 執(zhí)行查詢記錄1吗浩,Thread.sleep(3000);

3. 在事務(wù)1休眠期間没隘,事務(wù)2更新記錄1并提交懂扼;

4. 再次執(zhí)行查詢記錄1;

兩次結(jié)果不一致升略,發(fā)生不可重復(fù)讀微王。若改為isolation="REPEATABLE_READ",結(jié)果一致品嚣。

幻讀

在事務(wù)處理過(guò)程中,當(dāng)另一個(gè)事務(wù)將新行添加到正在讀取的記錄時(shí)钧大,會(huì)發(fā)生幻像讀取翰撑。

在執(zhí)行SELECT ... WHERE操作時(shí)沒(méi)有獲取范圍鎖定時(shí)可能會(huì)發(fā)生這種情況。 當(dāng)事務(wù)1重復(fù)有范圍的SELECT ... WHERE查詢并且在兩個(gè)操作之間,事務(wù)2創(chuàng)建(即INSERT)滿足WHERE的新行(即眶诈,在目標(biāo)表中)時(shí)涨醋,幻像讀取異常是非重復(fù)讀取的特例。

幻讀sql

重現(xiàn)步驟:

1. 設(shè)置propagation="REQUIRED" isolation="REPEATABLE_READ"逝撬;

2. 執(zhí)行查詢記錄10-30浴骂,Thread.sleep(3000);

3. 在事務(wù)1休眠期間宪潮,事務(wù)2更新記錄10-30并提交溯警;

4. 再次執(zhí)行查詢記錄10-30;

兩次結(jié)果一致狡相,沒(méi)有發(fā)生幻讀梯轻。有可能是一定幾率的。

為了重現(xiàn)幻讀尽棕,下面我又試了幾種配置:

重現(xiàn)幻讀嘗試


注意:

數(shù)據(jù)庫(kù)要關(guān)閉一級(jí)緩存喳挑,不然同樣的查詢,執(zhí)行兩次滔悉,第二次拿到的會(huì)是緩存中的數(shù)據(jù)伊诵,可以在映射mapping中這樣配置:

關(guān)閉一級(jí)緩存

參考:

https://en.wikipedia.org/wiki/Isolation_(database_systems)

寫偏序——Write Skew。根本的原因是由于每個(gè)事務(wù)在更新過(guò)程中無(wú)法看到其他事務(wù)的更改的結(jié)果回官,導(dǎo)致各個(gè)事務(wù)提交之后的最終結(jié)果違反了一致性日戈。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市孙乖,隨后出現(xiàn)的幾起案子浙炼,更是在濱河造成了極大的恐慌,老刑警劉巖唯袄,帶你破解...
    沈念sama閱讀 212,029評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件弯屈,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡恋拷,警方通過(guò)查閱死者的電腦和手機(jī)资厉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,395評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)蔬顾,“玉大人宴偿,你說(shuō)我怎么就攤上這事【骰恚” “怎么了窄刘?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,570評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)舷胜。 經(jīng)常有香客問(wèn)我娩践,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,535評(píng)論 1 284
  • 正文 為了忘掉前任翻伺,我火速辦了婚禮材泄,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘吨岭。我一直安慰自己拉宗,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,650評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布辣辫。 她就那樣靜靜地躺著旦事,像睡著了一般。 火紅的嫁衣襯著肌膚如雪络它。 梳的紋絲不亂的頭發(fā)上族檬,一...
    開(kāi)封第一講書(shū)人閱讀 49,850評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音化戳,去河邊找鬼单料。 笑死,一個(gè)胖子當(dāng)著我的面吹牛点楼,可吹牛的內(nèi)容都是我干的扫尖。 我是一名探鬼主播,決...
    沈念sama閱讀 39,006評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼掠廓,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼换怖!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起蟀瞧,我...
    開(kāi)封第一講書(shū)人閱讀 37,747評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤沉颂,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后悦污,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體铸屉,經(jīng)...
    沈念sama閱讀 44,207評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,536評(píng)論 2 327
  • 正文 我和宋清朗相戀三年切端,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了彻坛。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,683評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡踏枣,死狀恐怖昌屉,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情茵瀑,我是刑警寧澤间驮,帶...
    沈念sama閱讀 34,342評(píng)論 4 330
  • 正文 年R本政府宣布,位于F島的核電站瘾婿,受9級(jí)特大地震影響蜻牢,放射性物質(zhì)發(fā)生泄漏烤咧。R本人自食惡果不足惜偏陪,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,964評(píng)論 3 315
  • 文/蒙蒙 一抢呆、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧笛谦,春花似錦抱虐、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,772評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至灶轰,卻和暖如春谣沸,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背笋颤。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,004評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工乳附, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人伴澄。 一個(gè)月前我還...
    沈念sama閱讀 46,401評(píng)論 2 360
  • 正文 我出身青樓赋除,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親非凌。 傳聞我的和親對(duì)象是個(gè)殘疾皇子举农,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,566評(píng)論 2 349

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