什么是事務(wù)(Transaction)?
是指作為單個(gè)邏輯工作單元執(zhí)行的一系列操作,要么完全地執(zhí)行绿映,要么完全地不執(zhí)行。 事務(wù)處理可以確保除非事務(wù)性單元內(nèi)的所有操作都成功完成,否則不會(huì)永久更新面向數(shù)據(jù)的資源叉弦。通過將一組相關(guān)操作組合為一個(gè)要么全部成功要么全部失敗的單元丐一,可以簡(jiǎn)化錯(cuò)誤恢復(fù)并使應(yīng)用程序更加可靠。一個(gè)邏輯工作單元要成為事務(wù)淹冰,必須滿足所謂的ACID(原子性脖苏、一致性胳岂、隔離性和持久性)屬性。事務(wù)是數(shù)據(jù)庫(kù)運(yùn)行中的一個(gè)邏輯工作單位,由DBMS中的事務(wù)管理子系統(tǒng)負(fù)責(zé)事務(wù)的處理水由。
舉個(gè)例子加深一下理解:同一個(gè)銀行轉(zhuǎn)賬,A轉(zhuǎn)1000塊錢給B硫兰,這里存在兩個(gè)操作篓冲,一個(gè)是A賬戶扣款1000元,兩一個(gè)操作是B賬戶增加1000元瘪弓,兩者就構(gòu)成了轉(zhuǎn)賬這個(gè)事務(wù)垫蛆。
- 兩個(gè)操作都成功,A賬戶扣款1000元腺怯,B賬戶增加1000元袱饭,事務(wù)成功
- 兩個(gè)操作都失敗,A賬戶和B賬戶金額都沒變呛占,事務(wù)失敗
最后思考一下虑乖,怎么樣會(huì)出現(xiàn)A賬戶扣款1000元,B賬戶金額不變晾虑?如果你是把兩個(gè)操作放在一個(gè)事務(wù)里面疹味,并且是數(shù)據(jù)庫(kù)提供的內(nèi)在事務(wù)支持,那就不會(huì)有問題帜篇,但是開發(fā)人員把兩個(gè)操作放在兩個(gè)事務(wù)里面糙捺,而第二個(gè)事務(wù)失敗就會(huì)出現(xiàn)中間狀態(tài)。現(xiàn)實(shí)中自己實(shí)現(xiàn)的分布式事務(wù)處理不當(dāng)也會(huì)出現(xiàn)中間狀態(tài)笙隙,這并不是事務(wù)的錯(cuò)洪灯,事務(wù)本身就是規(guī)定不會(huì)出現(xiàn)中間狀態(tài),是事務(wù)實(shí)現(xiàn)者做出來的方案有問題竟痰。
事務(wù)的4個(gè)特性
原子性(Atomic):事務(wù)必須是原子工作單元签钩;對(duì)于其數(shù)據(jù)修改,要么全都執(zhí)行坏快,要么全都不執(zhí)行铅檩。通常,與某個(gè)事務(wù)關(guān)聯(lián)的操作具有共同的目標(biāo)莽鸿,并且是相互依賴的柠并。如果系統(tǒng)只執(zhí)行這些操作的一個(gè)子集,則可能會(huì)破壞事務(wù)的總體目標(biāo)。原子性消除了系統(tǒng)處理操作子集的可能性臼予。
一致性(Consistency):事務(wù)的一致性指的是在一個(gè)事務(wù)執(zhí)行之前和執(zhí)行之后數(shù)據(jù)庫(kù)都必須處于一致性狀態(tài)鸣戴。這種特性稱為事務(wù)的一致性。假如數(shù)據(jù)庫(kù)的狀態(tài)滿足所有的完整性約束粘拾,就說該數(shù)據(jù)庫(kù)是一致的窄锅。
隔離性(Isolation):由并發(fā)事務(wù)所作的修改必須與任何其它并發(fā)事務(wù)所作的修改隔離。事務(wù)查看數(shù)據(jù)時(shí)數(shù)據(jù)所處的狀態(tài)缰雇,到底是另一個(gè)事務(wù)執(zhí)行之前的狀態(tài)還是中間某個(gè)狀態(tài)入偷,相互之間存在什么影響,是可以通過隔離級(jí)別的設(shè)置來控制的械哟。
持久性(Durability):事務(wù)結(jié)束后疏之,事務(wù)處理的結(jié)果必須能夠得到固化,即寫入數(shù)據(jù)庫(kù)文件中即使機(jī)器宕機(jī)數(shù)據(jù)也不會(huì)丟失暇咆,它對(duì)于系統(tǒng)的影響是永久性的锋爪。
事務(wù)并發(fā)控制
我們從另外一個(gè)方向來說說,如果不對(duì)事務(wù)進(jìn)行并發(fā)控制爸业,我們看看數(shù)據(jù)庫(kù)并發(fā)操作是會(huì)有那些異常情形其骄,有些使我們可以接受的,有些是不能接受的扯旷,注意這里的異常就是特定語(yǔ)境下的拯爽,并不一定就是錯(cuò)誤什么的。假設(shè)有一個(gè)order表钧忽,有個(gè)字段叫count毯炮,作為計(jì)數(shù)用,當(dāng)前值為100
第一類丟失更新(Update Lost):此種更新丟失是因?yàn)榛貪L的原因耸黑,所以也叫回滾丟失桃煎。此時(shí)兩個(gè)事務(wù)同時(shí)更新count,兩個(gè)事務(wù)都讀取到100崎坊,事務(wù)一更新成功并提交备禀,count=100+1=101洲拇,事務(wù)二出于某種原因更新失敗了奈揍,然后回滾,事務(wù)二就把count還原為它一開始讀到的100赋续,此時(shí)事務(wù)一的更新就這樣丟失了男翰。
臟讀(Dirty Read):此種異常時(shí)因?yàn)橐粋€(gè)事務(wù)讀取了另一個(gè)事務(wù)修改了但是未提交的數(shù)據(jù)。舉個(gè)例子纽乱,事務(wù)一更新了count=101蛾绎,但是沒有提交,事務(wù)二此時(shí)讀取count,值為101而不是100租冠,然后事務(wù)一出于某種原因回滾了鹏倘,然后第二個(gè)事務(wù)讀取的這個(gè)值就是噩夢(mèng)的開始。
不可重復(fù)讀(Not Repeatable Read):此種異常是一個(gè)事務(wù)對(duì)同一行數(shù)據(jù)執(zhí)行了兩次或更多次查詢顽爹,但是卻得到了不同的結(jié)果纤泵,也就是在一個(gè)事務(wù)里面你不能重復(fù)(即多次)讀取一行數(shù)據(jù),如果你這么做了镜粤,不能保證每次讀取的結(jié)果是一樣的捏题,有可能一樣有可能不一樣。造成這個(gè)結(jié)果是在兩次查詢之間有別的事務(wù)對(duì)該行數(shù)據(jù)做了更新操作肉渴。舉個(gè)例子公荧,事務(wù)一先查詢了count,值為100同规,此時(shí)事務(wù)二更新了count=101循狰,事務(wù)一再次讀取count,值就會(huì)變成101,兩次讀取結(jié)果不一樣捻浦。
第二類丟失更新(Second Update Lost):此種更新丟失是因?yàn)楦卤黄渌聞?wù)給覆蓋了晤揣,也可以叫覆蓋丟失。舉個(gè)例子朱灿,兩個(gè)事務(wù)同時(shí)更新count昧识,都讀取100這個(gè)初始值,事務(wù)一先更新成功并提交盗扒,count=100+1=101跪楞,事務(wù)二后更新成功并提交,count=100+1=101,由于事務(wù)二count還是從100開始增加侣灶,事務(wù)一的更新就這樣丟失了甸祭。
幻讀(Phantom Read):幻讀和不可重復(fù)讀有點(diǎn)像,只是針對(duì)的不是數(shù)據(jù)的值而是數(shù)據(jù)的數(shù)量褥影。此種異常是一個(gè)事務(wù)在兩次查詢的過程中數(shù)據(jù)的數(shù)量不同池户,讓人以為發(fā)生幻覺,幻讀大概就是這么得來的吧凡怎。舉個(gè)例子校焦,事務(wù)一查詢order表有多少條記錄,事務(wù)二新增了一條記錄统倒,然后事務(wù)一查了一下order表有多少記錄寨典,發(fā)現(xiàn)和第一次不一樣,這就是幻讀房匆。
數(shù)據(jù)庫(kù)事務(wù)隔離級(jí)別
看到上面提到的幾種問題耸成,你可能會(huì)想报亩,我擦,這么多坑怎么辦啊井氢。其實(shí)上面幾種情況并不是一定都要避免的弦追,具體看你的業(yè)務(wù)要求,包括你數(shù)據(jù)庫(kù)的負(fù)載都會(huì)影響你的決定花竞。不知道大家發(fā)現(xiàn)沒有骗卜,上面各種異常情況都是多個(gè)事務(wù)之間相互影響造成的,這說明兩個(gè)事務(wù)之間需要某種方式將他們從某種程度上分開左胞,降低直至避免相互影響寇仓。這時(shí)候數(shù)據(jù)庫(kù)事務(wù)隔離級(jí)別就粉墨登場(chǎng)了,而數(shù)據(jù)庫(kù)的隔離級(jí)別實(shí)現(xiàn)一般是通過數(shù)據(jù)庫(kù)鎖實(shí)現(xiàn)的烤宙。
讀未提交(Read Uncommitted):該隔離級(jí)別指即使一個(gè)事務(wù)的更新語(yǔ)句沒有提交,但是別的事務(wù)可以讀到這個(gè)改變遍烦,幾種異常情況都可能出現(xiàn)。極易出錯(cuò)躺枕,沒有安全性可言服猪,基本不會(huì)使用。
讀已提交(Read Committed):該隔離級(jí)別指一個(gè)事務(wù)只能看到其他事務(wù)的已經(jīng)提交的更新拐云,看不到未提交的更新罢猪,消除了臟讀和第一類丟失更新,這是大多數(shù)數(shù)據(jù)庫(kù)的默認(rèn)隔離級(jí)別叉瘩,如Oracle,Sqlserver膳帕。
可重復(fù)讀(Repeatable Read):該隔離級(jí)別指一個(gè)事務(wù)中進(jìn)行兩次或多次同樣的對(duì)于數(shù)據(jù)內(nèi)容的查詢,得到的結(jié)果是一樣的薇缅,但不保證對(duì)于數(shù)據(jù)條數(shù)的查詢是一樣的危彩,只要存在讀改行數(shù)據(jù)就禁止寫,消除了不可重復(fù)讀和第二類更新丟失泳桦,這是Mysql數(shù)據(jù)庫(kù)的默認(rèn)隔離級(jí)別汤徽。
串行化(Serializable):意思是說這個(gè)事務(wù)執(zhí)行的時(shí)候不允許別的事務(wù)并發(fā)執(zhí)行.完全串行化的讀,只要存在讀就禁止寫,但可以同時(shí)讀灸撰,消除了幻讀谒府。這是事務(wù)隔離的最高級(jí)別,雖然最安全最省心浮毯,但是效率太低完疫,一般不會(huì)用。
下面是各種隔離級(jí)別對(duì)各異常的控制能力:
級(jí)別\異常 | 第一類更新丟失 | 臟讀 | 不可重復(fù)讀 | 第二類丟失更新 | 幻讀 |
---|---|---|---|---|---|
讀未提交 | Y | Y | Y | Y | Y |
讀已提交 | N | N | Y | Y | Y |
可重復(fù)讀 | N | N | N | N | Y |
串行化 | N | N | N | N | N |
數(shù)據(jù)庫(kù)鎖分類
一般可以分為兩類亲轨,一個(gè)是悲觀鎖趋惨,一個(gè)是樂觀鎖鸟顺,悲觀鎖一般就是我們通常說的數(shù)據(jù)庫(kù)鎖機(jī)制惦蚊,樂觀鎖一般是指用戶自己實(shí)現(xiàn)的一種鎖機(jī)制器虾,比如hibernate實(shí)現(xiàn)的樂觀鎖甚至編程語(yǔ)言也有樂觀鎖的思想的應(yīng)用。
悲觀鎖:顧名思義蹦锋,就是很悲觀兆沙,它對(duì)于數(shù)據(jù)被外界修改持保守態(tài)度,認(rèn)為數(shù)據(jù)隨時(shí)會(huì)修改莉掂,所以整個(gè)數(shù)據(jù)處理中需要將數(shù)據(jù)加鎖葛圃。悲觀鎖一般都是依靠關(guān)系數(shù)據(jù)庫(kù)提供的鎖機(jī)制,事實(shí)上關(guān)系數(shù)據(jù)庫(kù)中的行鎖憎妙,表鎖不論是讀寫鎖都是悲觀鎖库正。
悲觀鎖按照使用性質(zhì)劃分:
共享鎖(Share locks簡(jiǎn)記為S鎖):也稱讀鎖,事務(wù)A對(duì)對(duì)象T加s鎖厘唾,其他事務(wù)也只能對(duì)T加S褥符,多個(gè)事務(wù)可以同時(shí)讀,但不能有寫操作抚垃,直到A釋放S鎖喷楣。
排它鎖(Exclusivelocks簡(jiǎn)記為X鎖):也稱寫鎖,事務(wù)A對(duì)對(duì)象T加X鎖以后鹤树,其他事務(wù)不能對(duì)T加任何鎖铣焊,只有事務(wù)A可以讀寫對(duì)象T直到A釋放X鎖。
更新鎖(簡(jiǎn)記為U鎖):用來預(yù)定要對(duì)此對(duì)象施加X鎖罕伯,它允許其他事務(wù)讀曲伊,但不允許再施加U鎖或X鎖;當(dāng)被讀取的對(duì)象將要被更新時(shí)追他,則升級(jí)為X鎖熊昌,主要是用來防止死鎖的。因?yàn)槭褂霉蚕礞i時(shí)湿酸,修改數(shù)據(jù)的操作分為兩步婿屹,首先獲得一個(gè)共享鎖,讀取數(shù)據(jù)推溃,然后將共享鎖升級(jí)為排它鎖昂利,然后再執(zhí)行修改操作。這樣如果同時(shí)有兩個(gè)或多個(gè)事務(wù)同時(shí)對(duì)一個(gè)對(duì)象申請(qǐng)了共享鎖铁坎,在修改數(shù)據(jù)的時(shí)候蜂奸,這些事務(wù)都要將共享鎖升級(jí)為排它鎖。這些事務(wù)都不會(huì)釋放共享鎖而是一直等待對(duì)方釋放硬萍,這樣就造成了死鎖扩所。如果一個(gè)數(shù)據(jù)在修改前直接申請(qǐng)更新鎖,在數(shù)據(jù)修改的時(shí)候再升級(jí)為排它鎖朴乖,就可以避免死鎖祖屏。
悲觀鎖按照作用范圍劃分:
- 行鎖:鎖的作用范圍是行級(jí)別助赞,數(shù)據(jù)庫(kù)能夠確定那些行需要鎖的情況下使用行鎖,如果不知道會(huì)影響哪些行的時(shí)候就會(huì)使用表鎖袁勺。舉個(gè)例子雹食,一個(gè)用戶表user,有主鍵id和用戶生日birthday當(dāng)你使用update ... where id=?這樣的語(yǔ)句數(shù)據(jù)庫(kù)明確知道會(huì)影響哪一行期丰,它就會(huì)使用行鎖群叶,當(dāng)你使用update ... where birthday=?這樣的的語(yǔ)句的時(shí)候因?yàn)槭孪炔恢罆?huì)影響哪些行就可能會(huì)使用表鎖。
- 表鎖:鎖的作用范圍是整張表钝荡。
樂觀鎖:顧名思義街立,就是很樂觀,每次自己操作數(shù)據(jù)的時(shí)候認(rèn)為沒有人回來修改它埠通,所以不去加鎖几晤,但是在更新的時(shí)候會(huì)去判斷在此期間數(shù)據(jù)有沒有被修改,需要用戶自己去實(shí)現(xiàn)植阴。既然都有數(shù)據(jù)庫(kù)提供的悲觀鎖可以方便使用為什么要使用樂觀鎖呢蟹瘾?對(duì)于讀操作遠(yuǎn)多于寫操作的時(shí)候,大多數(shù)都是讀取掠手,這時(shí)候一個(gè)更新操作加鎖會(huì)阻塞所有讀取憾朴,降低了吞吐量。最后還要釋放鎖喷鸽,鎖是需要一些開銷的众雷,我們只要想辦法解決極少量的更新操作的同步問題。換句話說做祝,如果是讀寫比例差距不是非常大或者你的系統(tǒng)沒有響應(yīng)不及時(shí)砾省,吞吐量瓶頸問題,那就不要去使用樂觀鎖混槐,它增加了復(fù)雜度编兄,也帶來了額外的風(fēng)險(xiǎn)。
樂觀鎖實(shí)現(xiàn)方式:
- 版本號(hào)(記為version):就是給數(shù)據(jù)增加一個(gè)版本標(biāo)識(shí)声登,在數(shù)據(jù)庫(kù)上就是表中增加一個(gè)version字段狠鸳,每次更新把這個(gè)字段加1,讀取數(shù)據(jù)的時(shí)候把version讀出來悯嗓,更新的時(shí)候比較version件舵,如果還是開始讀取的version就可以更新了,如果現(xiàn)在的version比老的version大脯厨,說明有其他事務(wù)更新了該數(shù)據(jù)铅祸,并增加了版本號(hào),這時(shí)候得到一個(gè)無法更新的通知合武,用戶自行根據(jù)這個(gè)通知來決定怎么處理临梗,比如重新開始一遍涡扼。這里的關(guān)鍵是判斷version和更新兩個(gè)動(dòng)作需要作為一個(gè)原子單元執(zhí)行,否則在你判斷可以更新以后正式更新之前有別的事務(wù)修改了version夜焦,這個(gè)時(shí)候你再去更新就可能會(huì)覆蓋前一個(gè)事務(wù)做的更新,造成第二類丟失更新岂贩,所以你可以使用update ... where ... and version="old version"這樣的語(yǔ)句茫经,根據(jù)返回結(jié)果是0還是非0來得到通知,如果是0說明更新沒有成功萎津,因?yàn)関ersion被改了卸伞,如果返回非0說明更新成功。
- 時(shí)間戳(timestamp):和版本號(hào)基本一樣锉屈,只是通過時(shí)間戳來判斷而已荤傲,注意時(shí)間戳要使用數(shù)據(jù)庫(kù)服務(wù)器的時(shí)間戳不能是業(yè)務(wù)系統(tǒng)的時(shí)間。
- 待更新字段:和版本號(hào)方式相似颈渊,只是不增加額外字段遂黍,直接使用有效數(shù)據(jù)字段做版本控制信息,因?yàn)橛袝r(shí)候我們可能無法改變舊系統(tǒng)的數(shù)據(jù)庫(kù)表結(jié)構(gòu)俊嗽。假設(shè)有個(gè)待更新字段叫count,先去讀取這個(gè)count,更新的時(shí)候去比較數(shù)據(jù)庫(kù)中count的值是不是我期望的值(即開始讀的值)雾家,如果是就把我修改的count的值更新到該字段,否則更新失敗绍豁。java的基本類型的原子類型對(duì)象如AtomicInteger就是這種思想芯咧。
- 所有字段:和待更新字段類似,只是使用所有字段做版本控制信息竹揍,只有所有字段都沒變化才會(huì)執(zhí)行更新敬飒。
樂觀鎖幾種方式的區(qū)別:
新系統(tǒng)設(shè)計(jì)可以使用version方式和timestamp方式,需要增加字段芬位,應(yīng)用范圍是整條數(shù)據(jù)无拗,不論那個(gè)字段修改都會(huì)更新version,也就是說兩個(gè)事務(wù)更新同一條記錄的兩個(gè)不相關(guān)字段也是互斥的,不能同步進(jìn)行昧碉。舊系統(tǒng)不能修改數(shù)據(jù)庫(kù)表結(jié)構(gòu)的時(shí)候使用數(shù)據(jù)字段作為版本控制信息蓝纲,不需要新增字段,待更新字段方式只要其他事務(wù)修改的字段和當(dāng)前事務(wù)修改的字段沒有重疊就可以同步進(jìn)行晌纫,并發(fā)性更高税迷。
mysql事務(wù)隔離級(jí)別實(shí)戰(zhàn)
實(shí)踐是檢驗(yàn)真理的唯一標(biāo)準(zhǔn),掌握上面的理論之后锹漱,我們?cè)跀?shù)據(jù)庫(kù)上實(shí)戰(zhàn)一番家里更好地掌握也加深理解箭养,同時(shí)有助于解決實(shí)際問題。不同數(shù)據(jù)庫(kù)很多實(shí)現(xiàn)可能不同哥牍,這里以mysql為例講解各種隔離級(jí)別下的情況毕泌,測(cè)試表為user(id,name,gender,passwd,email)喝检。
隔離級(jí)別:read-uncommitted
臟讀測(cè)試流程:
- A設(shè)置隔離級(jí)別為read-uncommitted(注意這里未聲明都是session級(jí)別,而非全局的)撼泛,開啟事務(wù)挠说,查詢id=1的記錄
- B設(shè)置隔離級(jí)別為read-uncommitted,開啟事務(wù),修改id=1的記錄愿题,但不提交
- A再次查詢id=1的記錄损俭,和第一次查詢的比較一下
- B事務(wù)回滾,A事務(wù)回滾潘酗。
A:
B:
結(jié)論:A讀到了B沒有提交的內(nèi)容杆兵,隔離級(jí)別為read-uncommitted的時(shí)候出現(xiàn)臟讀。
第一類更新丟失測(cè)試流程:
- A設(shè)置隔離級(jí)別為read-uncommitted仔夺,開啟事務(wù)琐脏,查詢id=1的記錄
- B設(shè)置隔離級(jí)別為read-uncommitted,開啟事務(wù),查詢id=1的記錄
- A修改id=1的記錄
- B修改id=1的記錄
- A提交
- B回滾
- A在查詢一次id=1的記錄缸兔,看看自己的修改是否成功
結(jié)論:結(jié)果不如我所想的日裙,A的更新成功了,為什么呢惰蜜?A執(zhí)行update語(yǔ)句的時(shí)候?qū)υ摋l記錄加鎖了阅签,B這時(shí)候根本無法修改直至超時(shí),也就是至少在mysql中在read-uncommitted隔離級(jí)別下驗(yàn)證第一類丟失更新蝎抽,據(jù)了解有的數(shù)據(jù)庫(kù)好像可以設(shè)置不加鎖政钟,如果能夠不加鎖的話則可以實(shí)現(xiàn),也貼一下圖吧樟结。
A:
B:
不可重復(fù)讀測(cè)試流程(省略):
結(jié)論:流程和測(cè)試臟讀一樣养交,其實(shí)在第一次測(cè)試臟讀的時(shí)候就可以發(fā)現(xiàn)會(huì)出現(xiàn)不可重復(fù)讀,A兩次讀取id=1的數(shù)據(jù)內(nèi)容不同瓢宦。
第二類丟失更新流程:
- A開啟事務(wù)碎连,查詢order_id=1的記錄
- B開啟事務(wù),查詢order_id=1的記錄
- A把查出來的count加1后更新
- B把查出來的count加1更新
- A提交驮履,B也提交
A:
B:
結(jié)論:A的更新丟失鱼辙,我們希望的結(jié)果是3,而實(shí)際結(jié)果是2玫镐,跟java的多線程很像對(duì)不對(duì)倒戏,read-uncommitted隔離模式下會(huì)出現(xiàn)第二類丟失更新。
幻讀測(cè)試流程:
- A開啟事務(wù)恐似,查詢user表所有數(shù)據(jù)
- B開啟事務(wù)杜跷,新增一條記錄
- A再次查詢user表所有記錄,和第一次作比對(duì)
- A回滾,B回滾
A:
B:
結(jié)論:A兩次查詢?nèi)頂?shù)據(jù)結(jié)果不同葛闷,read-uncommitted隔離模式下會(huì)出現(xiàn)幻讀憋槐。
注:因?yàn)楹竺鎸?duì)這幾種異常情況的測(cè)試流程基本和上面一樣,個(gè)別有些差別讀者自己注意淑趾,另外注意更改隔離級(jí)別即可阳仔,就能看到對(duì)應(yīng)結(jié)果,后面的我只給出進(jìn)一步能解決的異常測(cè)試截圖,結(jié)論可以參照前面的對(duì)照表扣泊。
隔離級(jí)別:read-committed
臟讀測(cè)試截圖
A:
B:
結(jié)論:A沒有讀到B沒有提交的內(nèi)容近范,隔離級(jí)別為read-committed的時(shí)候不會(huì)出現(xiàn)臟讀。
隔離級(jí)別:repeatable-read
不可重復(fù)讀測(cè)試截圖
A:
B:
結(jié)論:A兩次讀取id=1的數(shù)據(jù)內(nèi)容相同旷赖,repeatable-read隔離模式下不會(huì)出現(xiàn)不可重復(fù)讀顺又。
隔離級(jí)別:Serializable
幻讀測(cè)試截圖
A:
B:
結(jié)論:因?yàn)锳事務(wù)未提交之前更卒,B事務(wù)插入操作無法獲得鎖而超時(shí)等孵,Serializable隔離模式下不會(huì)出現(xiàn)幻讀。