有一天鸡挠,快睡覺了,為了鞏固下數(shù)據(jù)庫知識彭沼,我跟我女朋友講了事務(wù)的概念姓惑。
她問我事務(wù)是什么按脚?是不是所有的sql都需要事務(wù)?
事務(wù)是什么
大家都知道唯沮,比如說我們要做一件事情介蛉,一般是有多個步驟才能完成币旧,當(dāng)然單個操作的也有。
那么我的理解就是猿妈,你要做的這一件事情就是一個事務(wù)吹菱,它是由一串操作來完成的巍虫。多個操作的前后順序就要做調(diào)度。
事務(wù)的幾大特性
那么我們在做一件事情的時候鳍刷,是否有時候會做到一半放棄呀垫言,這個時候為了保證不影響別的事情,咱們要清除剛剛未完成事情所造成的影響倾剿。這就叫做回滾筷频。
比如咱們做的事情是發(fā)郵件,在寫到一半的時候前痘,老板說取消發(fā)送這個方案凛捏,那咱們是要把剛剛寫的郵件刪除的。
那假如咱們把郵件發(fā)出去了芹缔,那么發(fā)郵件的事情就是做完了最欠,也就叫做事務(wù)已經(jīng)提交蚜点。
如果這時候老板叫我們?nèi)∠@個方案,其實發(fā)出去的郵件如果別人看到了陪拘,其實咱們是很難消除這個影響的左刽,也就是說馍佑,事務(wù)已經(jīng)提交拭荤,不能夠再撤回旦委,這個時候咱們只能執(zhí)行補(bǔ)償事務(wù),即咱們只能打電話告訴人家這個方案是不行的查辩。
原子性
上面說的這個取消發(fā)郵件的例子,就是事務(wù)的原子性萍倡。一般來說,原子性的意思就是一個操作不可再分,就像化學(xué)里面的原子一樣填硕,是最小單位。當(dāng)然原則上事務(wù)的原子性指的也是一個事務(wù)執(zhí)行的時候不能被打斷姻檀,要看作一個整體。那么實際上指的是事務(wù)的最終表現(xiàn)要么是成功的杂抽,要么是沒有出現(xiàn)過的赡矢。因為現(xiàn)實中,咱們要求數(shù)據(jù)庫執(zhí)行的性能啥的八酒,需要并發(fā)執(zhí)行事務(wù)。
隔離性
現(xiàn)在咱們知道事務(wù)是會并發(fā)執(zhí)行的,現(xiàn)在咱們來考慮一個場景:比如我要給我女朋友打錢报辱,這個時候剛好要還貸款米奸。假如打完錢就不夠還貸款了慢睡。如果兩個事務(wù)一起執(zhí)行的話,很可能會出現(xiàn)貸款公司剛剛讀出我的余額,發(fā)現(xiàn)夠還錢纬纪,下一剎那,我就把錢打給我女朋友了,這時候可能會出現(xiàn)貸款也還了,錢還轉(zhuǎn)了签则。哈哈钠惩,所以這時候就要求事務(wù)是隔離的篓跛。即Ti和Tj兩個事務(wù)并發(fā)執(zhí)行,但是Tj不能影響到Ti的執(zhí)行,也就是說狐援,Ti在自己執(zhí)行的時候厨诸,感覺到Tj是已經(jīng)執(zhí)行完了批钠,或者還沒開始執(zhí)行拷呆。他只看到自己在執(zhí)行。
一致性
假如咱們發(fā)現(xiàn),本來打算給女朋友匯2000的,結(jié)果自己賬號就扣了1000,女朋友還真收到2000了,這就是事務(wù)的不一致性。不一致性是需要程序員自己去保證的。也即使說,隔離執(zhí)行事務(wù)時,保證事務(wù)的一致性。按照我的理解就是,在不受其他事務(wù)的影響的情況下,你的需求是否正確執(zhí)行零抬。
持久性
假如過了幾天卸亮,我女朋友告訴問我怎么還沒打錢呀献酗,小孩都喝不上奶了,那么我一查,賬戶上的錢確實沒有打過去,但是明明記得已經(jīng)打了呀犯祠,應(yīng)該不是幻覺,這是數(shù)據(jù)庫估計出了啥事情把我們的事務(wù)給忘記了。
就算數(shù)據(jù)庫奔潰了,一旦恢復(fù)還是要記得咱們執(zhí)行過的事務(wù),這就是持久性。
事務(wù)的原子性和持久性
上面已經(jīng)介紹了事務(wù)的四大特性。這里我們講下數(shù)據(jù)庫時如何保證事務(wù)的這些特性的。
數(shù)據(jù)庫在執(zhí)行事務(wù)之前,會把事務(wù)需要執(zhí)行的操作記錄到日志中胖缤,當(dāng)我們回滾的時候涡真,就可以按照日志里的記錄反向執(zhí)行。或者在發(fā)生故障后萄喳,可以根據(jù)日志恢復(fù)數(shù)據(jù)。
數(shù)據(jù)庫是存在恢復(fù)系統(tǒng)的。具體的恢復(fù)策略可以在寫那章的時候講。
隔離性級別
首先講幾個概念
-
可串行化調(diào)度
之前咱們已經(jīng)說過調(diào)度,串行話調(diào)度其實就是交換兩個事務(wù)之間的調(diào)度順序,使其達(dá)到串行執(zhí)行的目的吨述。 -
可恢復(fù)調(diào)度
前面我們已經(jīng)說過邓夕,事務(wù)提交后時很難恢復(fù)的矿咕。A事務(wù)在操作B事務(wù)更行的數(shù)據(jù)后莲镣,立馬提交半火,然后B事務(wù)出了故障開始回滾瓤檐,那么A事務(wù)依賴B事務(wù)的修改其實是不存在的谴古。
所以一個可恢復(fù)的調(diào)度應(yīng)該是带饱,A事務(wù)做了修改执庐,B事務(wù)依賴這個修改猿诸,那么必須在A事務(wù)提交后B事務(wù)才能提交谷炸。 -
無級聯(lián)調(diào)度
假設(shè)B調(diào)用了A正在修改的數(shù)據(jù),然后C調(diào)用了B正在修改的數(shù)據(jù),那么當(dāng)A出錯回滾的時候僻造,B和C也都要回滾此迅,所以我們需要等A提交了再調(diào)用A的數(shù)據(jù)罢坝。這樣就不會有級聯(lián)調(diào)用了。
隔離性分為4個級別:
-
可串行化
可串行化調(diào)度 -
可重復(fù)讀
在一個事務(wù)中牲迫,任何兩次讀取同一個數(shù)據(jù)源時影晓,數(shù)據(jù)是一樣的锌订。 -
已提交讀
在讀取別的事務(wù)操作的數(shù)據(jù)之前,那個事務(wù)必須時已經(jīng)提交的。 -
未提交讀
在讀取別的事務(wù)操作的數(shù)據(jù)之前芹关,那個事務(wù)沒有提交也可以轴总。
下面我們看下盆佣,為什么會出現(xiàn)上述這4個級別庸娱。
可串行化調(diào)度基本上是沒有并發(fā)的疆液,類似與一個cpu利用不同時間片執(zhí)行不同任務(wù)一樣。
可重復(fù)讀是mysql默認(rèn)的隔離級別陕贮,意思是再同一個事務(wù)中堕油,不論何時兩次讀取同一個數(shù)據(jù)應(yīng)該都是一樣的。為什么會有這樣的需求肮之,我們看下面的掉缺。
已提交讀,其實也是不可重復(fù)讀戈擒。即要讀某個數(shù)據(jù)之前眶明,操作它的那個事務(wù)必須是已經(jīng)提交了,這樣可以避免臟讀筐高,但是是不可重復(fù)讀搜囱,因為當(dāng)我讀完之后,別的事務(wù)就可以改變我的數(shù)據(jù)柑土,那么下次讀數(shù)據(jù)就是不一樣了蜀肘。下面我們來舉一個例子:
假如你正在看作業(yè)題目,第一次看的時候是要求A+B的值冰单,等你在想的時候幌缝,題目變成A-B的值,這時你是不是會覺得見鬼了呢诫欠?
所以不可重復(fù)讀是會造成事務(wù)不一致的。
未提交讀很明顯浴栽,會發(fā)生臟讀荒叼,比如事務(wù)隨時可能會回滾,咱們很可能讀了不存在的數(shù)據(jù)典鸡。