****這些問(wèn)題的出現(xiàn)的原因****
之所以出現(xiàn)更新丟失,臟讀,和不可重復(fù)讀,幻讀,是因?yàn)楫?dāng)兩個(gè)事務(wù)同時(shí)進(jìn)行的時(shí)候,兩者之間互相不知道對(duì)方的存在,對(duì)自身所處的環(huán)境過(guò)分樂(lè)觀,從而沒(méi)有對(duì)操作的數(shù)據(jù)做一定的保護(hù)處理,最終導(dǎo)致一些問(wèn)題的出現(xiàn)。
而我們之前介紹的隔離級(jí)別,其實(shí)就是通過(guò)一定的機(jī)制和鎖來(lái)避免這樣的問(wèn)題,從而讓我們的并發(fā)事務(wù)可以正常的進(jìn)行。
****丟失更新問(wèn)題****

上圖中,由于事務(wù)A與事務(wù)B互相不知道對(duì)方的存在,因此導(dǎo)致了悲劇的發(fā)生。
如果避免這個(gè)問(wèn)題?
通過(guò)樂(lè)觀鎖可以解決這個(gè)問(wèn)題,在T9階段,事務(wù)A進(jìn)行更新余額操作的時(shí)候,SQL修改如下如下update table set amount=1100 where id=xxx **** and amount=1000****,通過(guò)加上一個(gè)金額的判斷,這樣的話,如果更改之前數(shù)據(jù)沒(méi)有修改則執(zhí)行成功,否則執(zhí)行失敗回滾。
****臟讀****
讀取的數(shù)據(jù)是不正確的數(shù)據(jù),即為臟讀。
mysql 中一個(gè)事務(wù)讀取了另一個(gè)未提交的并行事務(wù)寫(xiě)的數(shù)據(jù),那這個(gè)讀取就是臟讀。

圖中,事務(wù)A在T4階段讀取賬戶金額為110,這個(gè)數(shù)據(jù)就屬于臟數(shù)據(jù),因?yàn)檫@個(gè)數(shù)據(jù)是事務(wù)B撤銷掉的數(shù)據(jù),所以如果事務(wù)A使用數(shù)據(jù)110進(jìn)行后續(xù)的賬戶操作,就會(huì)引發(fā)問(wèn)題。
如果避免這個(gè)問(wèn)題?
read commited及以上隔離級(jí)別設(shè)定,一個(gè)事務(wù)只能讀取另一個(gè)事務(wù)已經(jīng)提交的數(shù)據(jù),就避免了上面的臟讀現(xiàn)象。
****不可重復(fù)讀****
不可重復(fù)讀,顧名思義,即不能多次重復(fù)去讀,因?yàn)樽x出來(lái)的結(jié)果不一樣,因此認(rèn)為存在不可重復(fù)讀的問(wèn)題。
read commited下設(shè)定,一個(gè)事務(wù)只能讀取另一個(gè)事務(wù)已經(jīng)提交的數(shù)據(jù),這就會(huì)出現(xiàn)不可重復(fù)讀的問(wèn)題。
repeatable read及以上級(jí)別設(shè)定,一個(gè)事務(wù)里,對(duì)數(shù)據(jù)的多次查詢都是讀取的一個(gè),無(wú)論該數(shù)據(jù)在中途是否被其他事務(wù)修改過(guò),因此也就避免了不可重復(fù)讀的問(wèn)題。
****幻讀****

上圖中,事務(wù)A一開(kāi)始查詢沒(méi)有數(shù)據(jù),但是插入記錄失敗,提示主鍵沖突,這種查詢明明沒(méi)有,插入?yún)s提示已經(jīng)存在的現(xiàn)象,叫做幻讀。
幻讀和不可重復(fù)讀類似,即兩次讀取的結(jié)果不一致,兩者的不同點(diǎn)在于,不可重復(fù)讀針對(duì)數(shù)據(jù)的修改造成的讀不一致,而幻讀針對(duì)數(shù)據(jù)的插入和刪除造成的讀不一致,如同發(fā)生幻覺(jué)一樣。
Repeatable read及以上級(jí)別通過(guò)間隙鎖來(lái)防止幻讀的出現(xiàn),即鎖定特定數(shù)據(jù)的前后間隙讓數(shù)據(jù)無(wú)法被插入