1 前言數據庫
知道數據庫的同窗確定都知道事務的概念,事務指的是一系列數據庫操做,它是保證數據庫正確性的基本邏輯單元,擁有ACID四個特性:原子性、一致性、隔離性與持久性。在分佈式數據庫系統中,分佈式事務繼承了傳統事務的定義,但也由於自身的分佈式特性而有其獨特特色。
網絡
本文將由淺入深,先從介紹傳統單機事務開始,而後繼續介紹分佈式事務的概念、特性以及經常使用的分佈式事務協議,最後談談本身對分佈式事務的一些想法。併發
但願經過閱讀本文,讓你們對分佈式事務有個基本的認知。app
2 事務的基本概念分佈式
在談分佈式事務以前,咱們先來講說傳統的單機數據庫中的事務概念吧,包括事務的定義以及事務的特性。
ide
2.1 事務的定義spa
常常聽人說,學會數據庫的增刪改查,就可以解決業務系統中百分之六七十的問題了。這裏說的增刪改查,對應的就是數據庫的數據存取操做,這些操做對於數據庫來講,就是事務了。
日誌
關於事務,先來講說概念性的東西:咱們將對數據庫的單個或多個操做序列的執行定義爲事務,這些操做要麼全作,要麼全不作,是一個不可分割的工做單位。舉個例子,下面這兩種組成狀況都叫作事務:code
由單個操做序列(一條SQL語句)組成的事務orm
select * from test
;
由多個操做序列(SQL語句)組成的事務
select * from test where id = 1;
update test(id, name) set name = 'john' where id = 1
;
固然,若是咱們沒有顯式聲明事務的話,數據庫則會給咱們自動地劃分事務,對於MySQL來講,沒有顯式聲明事務,則一條SQL語句就是一個事務,執行完便會自動提交。
一個事務由開始標識(begin_transaction)、數據庫操做和結束標識(commit或rollback)三部分組成。以下圖所示:
(事務的基本模型)
關於上圖的相關說明以下:
事務開始:begin_transaction,說明事務的開始;
數據庫上的操做:表現爲一條或多條SQL語句;
事務提交:commit_transaction,提交事務操做,操做生效;
事務回滾:rollback_transaction,事務取消,操做廢棄。
2.2 事務的特性
事務是對數據庫的一系列操做,是保證數據庫正確性的基本邏輯單元,這句話就決定了事務必須具有ACID四個特性,才能保證數據庫的正確性。下面咱們簡要說明下ACID四個特性的基本概念:
原子性
事務的原子性主要體如今事務中包含的操做要麼所有完成,要麼所有放棄,不存在中間狀態,即一部分操做成功,一部分操做失敗的狀態。
一致性
事務的一致性是指事務的執行結果必須使數據庫從一種一致性狀態變化到另外一種一致性狀態,而不會停留在某種中間狀態上。也就是說不管事務執行前仍是執行後,數據庫狀態均爲一致性狀態,處於這種狀態的數據庫才被認爲是正確的。因而可知,事務的一致性與原子性是密切相關的。
(事務的一致性)
隔離性
當多個事務的操做交叉執行時,若不加控制,一個事務的操做及其所使用的數據可能會對其餘事務形成影響。事務的隔離性是指:一個事務的執行既不能被其餘事務所幹擾,同時也不能干擾其餘事務。具體來說,一個沒有結束的事務在提交以前不容許將其結果暴露給其餘事務,這是由於未提交的事務有可能在之後的執行中回滾,所以,當前結果不必定是最終結果,而是一個無效的數據,不容許其餘事務使用這種無效數據。
持久性
事務的持久性體如今當一個事物提交後,系統保證該事務的結果不會因之後的故障而丟失,也就是說,事務一旦提交,它對數據庫的更改將是永久性的。
上述即爲事務的四個特性,ACID這四條特性起到了保證事務操做的正確性、維護數據庫的一致性及完整性的做用。
3 分佈式事務
講完了事務的基本概念,咱們正式開始談談分佈式事務。
分佈式事務與單機事務同樣都是由一組操做序列組成,不一樣的是單機事務只是在單機上執行,而分佈式事務則是在多臺機器上執行。下面咱們將介紹分佈式事務的定義、分佈式事務的提交協議(2PC、3PC)以及我對分佈式事務的一些見解。
3.1 分佈式事務的定義
咱們都知道事務是由一系列操做序列組成,對於單機事務,全部的這些操做序列都是在單機上面執行的,
以下圖所示:
(單機事務)
而對於分佈式數據庫系統,事務的一系列操做序列會被拆分爲子操做序列,而後在多臺機器上執行,以下圖所示:
(分佈式事務)
在分佈式數據庫中的事務即被稱爲分佈式事務,也叫全局事務,被拆分爲在各個機器上執行的子操做序列,稱爲子事務。
分佈式事務一樣具備ACID四個特性,可是由於分佈式數據庫的分佈特性,使其又有一些不一樣。例如,爲了保證分佈式事務的原子性,必須保證組成該全局事務的全部子事務要麼所有提交,要麼所有回滾,不容許出現有些場地上的子事務提交,而有些場地上的子事務回滾。
所以,在分佈式事務執行的過程當中,要比單機事務複雜的多,由於分佈式事務除了要保證各個子事務的ACID特性外,還須要對這些子事務進行協調,決定各個子事務的提交與回滾,以保證全局事務的ACID特性。另外,在分佈式事務中,還涉及大量的網絡通訊,須要考慮到網絡的影響。
經過上文,相信你們應該對分佈式事務有了一些概念上的瞭解,下面咱們將介紹分佈式事務的提交協議。
3.2 分佈式事務的提交協議
對於分佈式事務來說,全局事務的正確執行依賴各個子事務的正確執行。只有當各個局部操做都正確執行後,全局事務才能夠提交,當發生異常要回滾全局事務時,全部局部操做也應回滾。所以,全部子事務均正確提交是分佈式事務提交的前提。爲實現分佈式事務的提交,廣泛採用兩階段提交協議(2 Phase Commit),簡稱2PC協議。
咱們已經知道分佈式事務在執行時會被分解爲多個場地上的子事務來執行。爲協調各個場地上的子事務的執行,咱們須要一個協調者,而各個子事務的具體執行,須要本地的參與者來完成。爲進一步理解兩階段提交協議,咱們先了解下協調者與參與者這兩個概念:
協調者:協調各個子事務的執行,負責決定全部子事務的提交或回滾;
參與者:負責各個子事務的提交與回滾,並向協調者提出子事務的提交或回滾意向。
協調者與參與者的關係以下圖所示:
(協調者與參與者的關係)
協調者和每一個參與者均擁有一個本地日誌文件,用來記錄各自的執行過程。不管是協調者仍是參與者,他們在進行操做前都必須將該操做記錄到相應的日誌文件中,以用來進行事務故障恢復。
協調者能夠向各個參與者發送命令,使各個參與者在協調者的領導下執行命令,各個參與者也能夠將自身的命令執行狀態以應答的形式反饋給協調者,由協調者收集並分析這些應答以決定下一步的操做。
兩階段提交協議是爲了實現分佈式事務提交而採用的協議。其基本思想是把全局事務的提交分爲以下兩個階段:
決定階段:由協調者向各個參與者發出「預提交」(Prepare)命令,而後等待應答,若全部的參與者返回「準備提交」(Ready)應答,則該事務知足提交條件。若是至少有一個子事務返回「準備廢棄」(Abort)應答,則該事務不能提交;
執行階段:在事務具有提交條件的狀況下,協調者向各個參與者發出「提交」(Commit)命令,各個參與者執行提交;不然,協調者向各個參與者發出「廢棄」(Abort)命令,各個參與者執行回滾,放棄對數據庫的修改。不管是「提交」仍是「廢棄」,各參與者執行完畢後都須要向協調者返回「確認」(ACK)應答,通知協調者事務執行結束。
兩階段提交協議的基本思想能夠用下圖表示:
(兩階段提交協議示意圖)
說完了兩階段提交協議的基本思想,咱們來具體看看兩階段提交協議的基本流程。
兩階段提交協議的基本流程以下圖所示:
(兩階段提交協議的基本流程)
關於上圖的步驟說明以下:
協調者在徵求各參與者的意見以前,首先要在它的日誌文件中寫入一條「開始提交」(Begin_commit)的記錄。而後,協調者向全部參與者發送「預提交」(Prepare)命令,此時協調者進入等待狀態,等待收集各參與者的應答;
各個參與者接收到「預提交」(Prepare)命令後,根據狀況判斷其是否已經準備好提交子事務。若能夠提交,則在參與者日誌文件中寫入一條「準備提交」(Ready)的記錄,並將「準備提交」(Ready)的應答發送給協調者,不然,在參與者的日誌文件中寫入一條「準備廢棄」(Abort)的記錄,並將「準備廢棄」(Abort)的應答發送給協調者。發送應答後,參與者將進入等待狀態,等待協調者所作出的最終決定;
協調者收集各參與者發來的應答,判斷是否存在某個參與者發來「準備廢棄」的應答,若存在,則採起兩階段提交協議的「一票否決制」,在其日誌文件中寫入一條「決定廢棄」(Abort)的記錄,併發送「全局廢棄」(Abort)命令給各個參與者,不然,在其日誌中寫入一條「決定提交」(Commit)的記錄,向全部參與者發送「全局提交」(Commit)命令。此時,協調者再次進入等待狀態,等待收集各參與者的確認信息;
各個參與者接收到協調者發來的命令後,判斷該命令類型,若爲「全局提交」命令,則在其日誌文件中寫入一條「提交」(Commit)的記錄,並對子事務實施提交,不然,參與者在其日誌文件中寫入一條「廢棄」(Abort)的記錄,並對子事務實施廢棄。實施完畢後,各個參與者要向協調者發送確認信息(Ack);
當協調者接收到全部參與者發送的確認信息後,在其日誌文件中寫入「事務結束」(End_transaction)記錄,全局事務終止。
3.3 對分佈式事務的一點思考
上文對分佈式事務的基本概念及經常使用的分佈式提交協議(2PC)進行了一些說明,下面談談我對分佈式事務的一些見解。
關於兩階段提交協議,若參與者收到了協調者發送的「提交」命令時,說明其餘參與者均已向協調者發送了「準備提交」的應答,則參與者能夠提交其子事務,可是兩階段提交協議有一點不足,就是若是協調者故障或者網絡故障,致使參與者不能及時收到協調者發送的「提交」命令時,那麼參與者將處於等待狀態,直到得到所須要的信息後才能夠作出決定。
在故障恢復前,參與者的行爲將始終停留不前,子事務所佔用的系統資源也不能被釋放,這時咱們稱事務進入了阻塞狀態,阻塞狀態會下降系統的可靠性與可用性。
由於兩階段提交協議的上述缺點,因此三階段提交協議(3PC)被提出,三階段提交協議在必定程度上解決了兩階段提交協議中的阻塞問題,這是由於當協調者故障或是網絡故障時,參與者長時間未收到協調者的命令,參與者能夠經過啓動恢復處理過程,沒必要進入等待狀態而能夠獨立的作出決定。
三階段提交協議雖然能夠在必定程度上解決兩階段提交協議中的阻塞問題,但由於流程邏輯複雜,代碼編寫難度過高,也很難用於實際應用。
同時,爲了保證分佈式數據庫的正確性,除了須要分佈式事務的提交協議,咱們還須要分佈式事務的恢復策略,在發生故障的時候對事務進行恢復,在分佈式數據庫系統中,除了會出現單機數據庫中的故障外,還會出現網絡故障、參與者故障這些分佈式數據庫系統中特有的故障,針對每種故障發生的狀況,都須要有特定的恢復策略,可見分佈式事務的恢復更是一個複雜的問題。
從我的看來,我認爲完美的實現分佈式事務是一件頗具挑戰的事情,這可能也是目前不少產品都明確表示不建議開啓分佈式事務的緣由吧。
4 結語
本文主要討論了數據庫系統中事務相關的一些概念與知識,包括單機事務與分佈式事務以及我的對於分佈式事務的一些見解。
最後,本人能力有限,文中有不正確的地方還望你們可以指出,同時也但願本文能對你們有所幫助。
參考資料
《分佈式數據庫系統》.於戈 申德榮.機械工業出版社.2016年1月第2版