事務(wù)的概念
事務(wù)是訪問(wèn)并可能更新各種數(shù)據(jù)項(xiàng)的一個(gè)程序執(zhí)行單元
。
換句話說(shuō),一個(gè)或者多個(gè)數(shù)據(jù)庫(kù)操作的集合,這個(gè)集合必須構(gòu)成單一的邏輯工作單元
选调。
所謂單一的邏輯工作單元,舉個(gè)經(jīng)常用到的例子:銀行的轉(zhuǎn)賬功能灵份。
轉(zhuǎn)賬對(duì)于客戶來(lái)說(shuō)是一個(gè)單一的操作学歧,但是在數(shù)據(jù)庫(kù)層面則是多個(gè)操作的集合,那么這個(gè)集合就是單一的邏輯工作單元各吨。
MySQL提出事務(wù)的這個(gè)概念枝笨,是因?yàn)橐?guī)定了這些操作集合必須滿足的條件:AICD原則。
即把需要滿足AICD的的數(shù)據(jù)庫(kù)操作集合揭蜒,稱之為事務(wù)
横浑。
A(原子性,Atomicity)
即要么全做屉更,要么全不做
徙融。轉(zhuǎn)賬功能要么成功,要么失敗瑰谜,不存在中間態(tài)(A扣款成功欺冀,B接收失斒骷ā)。
I(隔離性隐轩,Isolation)
并發(fā)事務(wù)的執(zhí)行饺饭,相互之間不影響
。
即使保障每個(gè)事務(wù)的原子性职车,但是如果多個(gè)事務(wù)并發(fā)交錯(cuò)執(zhí)行瘫俊,仍然會(huì)導(dǎo)致結(jié)果不一致,如圖:
兩次轉(zhuǎn)賬并未串行執(zhí)行悴灵,而是交替執(zhí)行扛芽,導(dǎo)致A賬戶減少50,B賬戶卻多出了100积瞒。
C(一致性川尖,Consistency)
上述轉(zhuǎn)賬的例子就破壞了一致性。
所謂一致性茫孔,就是數(shù)據(jù)庫(kù)所處的狀態(tài)的必須符合現(xiàn)實(shí)世界的約束
叮喳。例如轉(zhuǎn)賬就必須保障A、B賬戶的總額是一定的银酬。
D(持久性,Durability)
在系統(tǒng)保證一個(gè)事務(wù)被正確執(zhí)行后筐钟,最終的結(jié)果要被持久性的保存下來(lái)
揩瞪,無(wú)論之后發(fā)生什么事故都不會(huì)將這次事務(wù)的結(jié)果丟失
。
事務(wù)的狀態(tài)
事務(wù)并非總能順利執(zhí)行成功篓冲,會(huì)存在各種情況影響事務(wù)的順利推進(jìn)李破,為了準(zhǔn)備了解事務(wù),應(yīng)對(duì)不同的情況壹将。
需要更準(zhǔn)確定義事務(wù)成功完成
的含義嗤攻,為此定義了事務(wù)的不同的狀態(tài)及其流轉(zhuǎn)過(guò)程。如圖:
活動(dòng)的(active): 初始狀態(tài)诽俯,數(shù)據(jù)庫(kù)正在執(zhí)行事務(wù)妇菱。
部分提交的(partially commited): 最后一條語(yǔ)句執(zhí)行完后,但還沒(méi)有刷新到磁盤暴区。
失敗的(failed): 在活動(dòng)狀態(tài)或者部分提交狀態(tài)闯团,因?yàn)橄到y(tǒng)錯(cuò)誤、斷電等原因無(wú)法執(zhí)行仙粱,或者人為停止執(zhí)行房交。
中止的(aborted): 事務(wù)執(zhí)行失敗,需要將已經(jīng)對(duì)數(shù)據(jù)庫(kù)造成的影響撤銷伐割,執(zhí)行回滾操作候味,執(zhí)行完后即為中止?fàn)顟B(tài)刃唤。
提交的(commited): 事務(wù)順利執(zhí)行完成,并成功刷新到磁盤白群。
可以發(fā)現(xiàn)尚胞,中止?fàn)顟B(tài)和提交狀態(tài)才是事務(wù)的最終狀態(tài)
。
并發(fā)問(wèn)題
并發(fā)事務(wù)必須符合AICD原則川抡,來(lái)保障數(shù)據(jù)的正確性辐真。如果不滿足AICD,并發(fā)執(zhí)行訪問(wèn)相同的數(shù)據(jù)崖堤,將會(huì)產(chǎn)生臟寫侍咱、臟讀、不可重復(fù)讀密幔、幻讀
等一系列問(wèn)題楔脯。
臟寫
如果一個(gè)事務(wù)修改了另一個(gè)尚未提交的事務(wù)修改過(guò)的數(shù)據(jù)
,即為臟寫胯甩。如下圖:
T2修改了T1還沒(méi)提交的數(shù)據(jù)昧廷,將number更新為20,但是T1未提交偎箫,意味著可能會(huì)回滾木柬,如果T1發(fā)生rollback,那么T2更新的值20也將不復(fù)存在淹办。
臟讀
如果一個(gè)事務(wù)讀到了另一個(gè)未提交事務(wù)修改過(guò)的數(shù)據(jù)
眉枕,即為臟讀,如下圖:
T1未提交意味著可能會(huì)回滾怜森。當(dāng)T2讀到number值為20后速挑,T1發(fā)生回滾,T2就讀到了一個(gè)不存在的數(shù)據(jù)副硅。
不可重復(fù)讀
在一個(gè)事務(wù)內(nèi)姥宝,對(duì)相同的數(shù)據(jù)在不同的時(shí)刻讀取到的值卻不同
,即不可重復(fù)讀恐疲。
它與臟讀的區(qū)別
在于:前者讀到的是其他事務(wù)提交后
的數(shù)據(jù)腊满,后者讀到的是其他事務(wù)未提交
的數(shù)據(jù)培己。 如下圖:
在T2事務(wù)內(nèi)疮蹦,兩次讀取值分別是10與20愕乎,讀到的都是TI更新提交后的值(隱式事務(wù))感论,對(duì)于T2來(lái)說(shuō)發(fā)生了不可重復(fù)讀比肄。
幻讀
如果一個(gè)事務(wù)以相同的查詢條件在兩個(gè)不同的時(shí)刻查詢芳绩,在第二次查詢中妥色,查詢到了其他事務(wù)插入的數(shù)據(jù)嘹害,即發(fā)生了幻讀笔呀。
幻讀強(qiáng)調(diào)的是數(shù)據(jù)插入時(shí)產(chǎn)生的數(shù)據(jù)不一致许师,區(qū)別與不可重復(fù)讀對(duì)于相同數(shù)據(jù)的更新操作惨驶。 如下圖:
T2在事務(wù)內(nèi),第二次查詢讀到了T1插入的no=50的數(shù)據(jù)纳击,發(fā)生了幻讀。
事務(wù)隔離級(jí)別
針對(duì)并發(fā)事務(wù)下的問(wèn)題堡赔,MySQL根據(jù)問(wèn)題的嚴(yán)重性程度善已,設(shè)立了不同的隔離級(jí)別來(lái)規(guī)避悉稠。
問(wèn)題嚴(yán)重性程度:臟寫>臟讀>不可重復(fù)讀>幻讀
的猛。
四種隔離級(jí)別:
未提交讀: 允許讀取未提交數(shù)據(jù)卦尊,級(jí)別最低猫牡。
已提交的:只允許讀取已提交數(shù)據(jù)淌友,但不要求可重復(fù)讀震庭。
可重復(fù)讀:只允許讀取已提交數(shù)據(jù)器联,并要求一個(gè)事務(wù)兩次讀取一個(gè)數(shù)據(jù)項(xiàng)期間拨拓,其他事務(wù)不允許更新數(shù)據(jù)渣磷。
可串行化:保證事務(wù)可串行化調(diào)度醋界,級(jí)別最高。
隔離級(jí)別與問(wèn)題發(fā)生的關(guān)系如下圖:
如圖可以發(fā)現(xiàn)臟寫在每種隔離級(jí)別下都不允許發(fā)生。
可串行化可以解決所有的問(wèn)題脂新。但為什么不只使用可串行化戏羽,而提供其他的隔離級(jí)別呢妄讯?
當(dāng)然是為了效率考慮亥贸,隔離級(jí)別越高,效率越低朴摊。所以只能舍棄一部分隔離性換取性能
甚纲。
MySQL如何實(shí)現(xiàn)隔離級(jí)別的,再接下來(lái)的學(xué)習(xí)中在分享春哨。