事務(wù)(Transaction)是由一系列對(duì)系統(tǒng)中數(shù)據(jù)進(jìn)行訪問(wèn)與更新的操作所組成的一個(gè)程序執(zhí)行邏輯單元(Unit),狹義上的事務(wù)特指數(shù)據(jù)庫(kù)事務(wù)。一方面,當(dāng)多個(gè)應(yīng)用程序并發(fā)訪問(wèn)數(shù)據(jù)庫(kù)時(shí),事務(wù)可以在這些應(yīng)用程序之間提供一個(gè)隔離方法,以防止彼此的操作互相干擾。另一方面,事務(wù)為數(shù)據(jù)庫(kù)操作序列提供了一個(gè)從失敗中恢復(fù)到正常狀態(tài)的方法,同時(shí)提供了數(shù)據(jù)庫(kù)即使在異常狀態(tài)下仍能保持數(shù)據(jù)一致性的方法。
事務(wù)具有四個(gè)特征,分別是原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)和持久性(Durability),簡(jiǎn)稱(chēng)為事務(wù)的ACID特性。
A原子性
事務(wù)的原子性是指事務(wù)必須是一個(gè)原子的操作序列單元。事務(wù)中包含的各項(xiàng)操作在一次執(zhí)行過(guò)程中,只允許出現(xiàn)其中一種狀態(tài):全部成功執(zhí)行 和全部不執(zhí)行。
任何一項(xiàng)操作失敗將導(dǎo)致整個(gè)事務(wù)失敗,同時(shí)其他已經(jīng)被執(zhí)行的操作將被撤銷(xiāo)并回滾,只有所有的操作全部成功,整個(gè)事務(wù)才算是成功完成。
C一致性
事務(wù)的一致性是指事務(wù)的執(zhí)行不能破壞數(shù)據(jù)庫(kù)數(shù)據(jù)的完整性和一致性,一個(gè)事務(wù)在執(zhí)行之前和執(zhí)行之后,數(shù)據(jù)庫(kù)都必須處于一致性狀態(tài)。也就是說(shuō),事務(wù)執(zhí)行的結(jié)果必須是使數(shù)據(jù)庫(kù)從一個(gè)一致性狀態(tài)轉(zhuǎn)變到另一個(gè)一致性狀態(tài),因此當(dāng)數(shù)據(jù)庫(kù)只包含成功事務(wù)提交的結(jié)果時(shí),就能說(shuō)數(shù)據(jù)庫(kù)處于一致性狀態(tài)。而如果數(shù)據(jù)庫(kù)系統(tǒng)在運(yùn)行過(guò)程中發(fā)生故障,有些事務(wù)尚未完成就被迫中斷,這些未完成的事務(wù)對(duì)數(shù)據(jù)庫(kù)所做的修改有一部分已寫(xiě)入物理數(shù)據(jù)庫(kù),這時(shí)數(shù)據(jù)庫(kù)就處于一種不正確的狀態(tài),或者說(shuō)是不一致的狀態(tài)。
I隔離性
事務(wù)的隔離性是指在并發(fā)環(huán)境中,并發(fā)的事務(wù)是相互隔離的,一個(gè)事務(wù)的執(zhí)行不能被其他事務(wù)干擾。也就是說(shuō),不同的事務(wù)并發(fā)操縱相同的數(shù)據(jù)時(shí),每個(gè)事務(wù)都有各自完整的數(shù)據(jù)空間,即一個(gè)事務(wù)內(nèi)部的操作及使用的數(shù)據(jù)對(duì)其他并發(fā)事務(wù)是隔離的,并發(fā)執(zhí)行的各個(gè)事務(wù)之間不能互相干擾。
在標(biāo)準(zhǔn) SQL 規(guī)范中,定義了 4 個(gè)事務(wù)隔離級(jí)別,不同的隔離級(jí)別對(duì)事務(wù)的處理不同,如未授權(quán)讀取、授權(quán)讀取、可重復(fù)讀取和串行化。
1) 未授權(quán)讀取也被稱(chēng)為讀未提交( Read? Uncommitted),該隔離級(jí)別允許臟讀取,其隔離級(jí)別最低。如果一個(gè)事務(wù)正在處理某一數(shù)據(jù),并對(duì)其進(jìn)行了更新,但同時(shí)尚未完成事務(wù),因此還沒(méi)有進(jìn)行事務(wù)提交;而與此同時(shí),允許另一個(gè)事務(wù)也能夠訪問(wèn)該數(shù)據(jù)。舉個(gè)例子,事務(wù)B能夠看到在事務(wù)A操作過(guò)程中的所有中間值(如1變成2、2變成3等),而對(duì)這一系列的中間值的讀取就是未授權(quán)讀取。
疑問(wèn):事務(wù)未完成但數(shù)據(jù)如何更新的?
2) 授權(quán)讀取也被稱(chēng)為讀已提交(Read? Committed),它和未授權(quán)讀取非常相近,唯一的區(qū)別就是授權(quán)讀取只允許獲取已經(jīng)被提交的數(shù)據(jù)。事務(wù)B無(wú)法看到在事務(wù) A 操作過(guò)程中的所有中間值,只能看到最終的10,即授權(quán)讀取允許不可重復(fù)讀取(針對(duì)事務(wù)B來(lái)說(shuō),不可重復(fù)讀取到值1)。
3) 可重復(fù)讀取(Repeatable Read),保證在事務(wù)處理過(guò)程中,多次讀取同一個(gè)數(shù)據(jù)時(shí),其值都和事務(wù)開(kāi)始時(shí)刻是一致的。因此該事務(wù)級(jí)別禁止了不可重復(fù)讀取和臟讀取,但是有可能出現(xiàn)幻影數(shù)據(jù)。所謂幻影數(shù)據(jù),就是指同樣的事務(wù)操作,在前后兩個(gè)時(shí)間段內(nèi)執(zhí)行對(duì)同一個(gè)數(shù)據(jù)項(xiàng)的讀取,可能出現(xiàn)不一致的結(jié)果??芍貜?fù)讀取隔離級(jí)別能夠保證事務(wù) B 在第一次事務(wù)操作過(guò)程中,始終對(duì)數(shù)據(jù)項(xiàng)讀取到 1,但是授權(quán)提交中,未結(jié)束的事務(wù)B采用同樣的查詢(xún)方式,就可能會(huì)讀取到10或20。
4) 串行化(Serializable)是最嚴(yán)格的事務(wù)隔離級(jí)別。它要求所有事務(wù)都被串行執(zhí)行,即事務(wù)只能一個(gè)接一個(gè)地進(jìn)行處理,不能并發(fā)執(zhí)行。
以上4個(gè)隔離級(jí)別的隔離性依次增強(qiáng),分別解決不同的問(wèn)題,下表對(duì)這4個(gè)隔離級(jí)別進(jìn)行了一個(gè)簡(jiǎn)單的對(duì)比。

事務(wù)隔離級(jí)別越高,就越能保證數(shù)據(jù)的完整性和一致性,但同時(shí)對(duì)并發(fā)性能的影響也越大。通常,對(duì)于絕大多數(shù)的應(yīng)用程序來(lái)說(shuō),可以優(yōu)先考慮將數(shù)據(jù)庫(kù)系統(tǒng)的隔離級(jí)別設(shè)置為授權(quán)讀取(讀已提交),這能夠在避免臟讀取的同時(shí)保證較好的并發(fā)性能。盡管這種事務(wù)隔離級(jí)別會(huì)導(dǎo)致不可重復(fù)讀、虛讀和第二類(lèi)丟失更新等并發(fā)問(wèn)題,但較為科學(xué)的做法是在可能出現(xiàn)這類(lèi)問(wèn)題的個(gè)別場(chǎng)合中,由應(yīng)用程序主動(dòng)采用悲觀鎖或樂(lè)觀鎖來(lái)進(jìn)行事務(wù)控制。
D持久性
事務(wù)的持久性也被稱(chēng)為永久性,是指一個(gè)事務(wù)一旦提交,它對(duì)數(shù)據(jù)庫(kù)中對(duì)應(yīng)數(shù)據(jù)的狀態(tài)變更就應(yīng)該是永久性的。換句話說(shuō),一旦某個(gè)事務(wù)成功結(jié)束,那么它對(duì)數(shù)據(jù)庫(kù)所做的更新就必須被永久保存下來(lái)——即使發(fā)生系統(tǒng)崩潰或機(jī)器宕機(jī)等故障,只要數(shù)據(jù)庫(kù)能夠重新啟動(dòng),那么一定能夠?qū)⑵浠謴?fù)到事務(wù)成功結(jié)束時(shí)的狀態(tài)。
ACID是一個(gè)解決本地事務(wù)和集中式事務(wù)處理的經(jīng)典方法論,是一個(gè)很成熟的已經(jīng)被實(shí)踐證明的處理數(shù)據(jù)一致性的模型。
當(dāng)然分布式事務(wù)也可以被定義為一種嵌套型的事務(wù),同時(shí)也就具有了ACID事務(wù)特性。由于在分布式事務(wù)中,各個(gè)子事務(wù)的執(zhí)行是分布式的,因此要實(shí)現(xiàn)一種能夠保證ACID特性的分布式事務(wù)處理系統(tǒng)就顯得格外復(fù)雜。
什么是分布式事務(wù)?
指事務(wù)的參與者、支持事務(wù)的服務(wù)器、資源服務(wù)器以及事務(wù)管理器分別位于分布式系統(tǒng)的不同節(jié)點(diǎn)之上。通常一個(gè)分布式事務(wù)中會(huì)涉及對(duì)多個(gè)數(shù)據(jù)源或業(yè)務(wù)系統(tǒng)的操作。
一個(gè)最典型的分布式事務(wù)場(chǎng)景:
一個(gè)跨銀行的轉(zhuǎn)賬操作涉及調(diào)用兩個(gè)異地的銀行服務(wù),其中一個(gè)是本地銀行提供的取款服務(wù),另一個(gè)則是目標(biāo)銀行提供的存款服務(wù),這兩個(gè)服務(wù)本身是無(wú)狀態(tài)并且是互相獨(dú)立的,共同構(gòu)成了一個(gè)完整的分布式事務(wù)。如果從本地銀行取款成功,但是因?yàn)槟撤N原因存款服務(wù)失敗了,那么就必須回滾到取款前的狀態(tài),否則用戶(hù)可能會(huì)發(fā)現(xiàn)自己的錢(qián)不翼而飛了。
從上面這個(gè)例子中,我們可以看到,一個(gè)分布式事務(wù)可以看作是由多個(gè)分布式的操作序列組成的,取款服務(wù)和存款服務(wù),通常可以把這一系列分布式的操作序列稱(chēng)為子事務(wù)。有沒(méi)有發(fā)現(xiàn)要保證ACID特性的分布式事務(wù)處理比本地事務(wù)或集中式事務(wù)處理更復(fù)雜些。
如何解決分布式事務(wù)處理的一致性問(wèn)題?下文再續(xù)。
摘取自倪超《從Paxos到Zookeeper:分布式一致性原理與實(shí)踐》