MySQL中事務的分類
從事務理論的角度來看,可以把事務分為以下幾種型別
扁平事務(Flat Transactions)
帶有儲存點的扁平事務(Flat Transactions with Savepoints)
鏈事務(Chained Transactions)
巢狀事務(Nested Transactions)
分散式事務(Distributed Transactions)
扁平事務 是事務型別中最簡單的一種,但是在實際生產環境中,這可能是使用最頻繁的事務,在扁平事務中,所有操作都處於同一層次,其由BEGIN WORK開始,由COMMIT WORK或ROLLBACK WORK結束,其間的操作是源自的,要麼都執行,要麼都回滾,因此扁平事務是應用程式稱為原子操作的的基本組成模組
下面顯示了扁平事務的三種不同結果
給出的扁平事務的三種情況,同時也給出了一個典型的事務處理應用中,每個結果大概佔用的百分比。再次提醒,扁平事務雖然簡單,但是在實際環境中使用最為頻繁,也正因為其簡單,使用頻繁,故每個資料庫系統都實現了對扁平事務的支援
扁平事務的主要限制是不能提交或者回滾事務的某一部分,或分幾個步驟提交。下面給出一個扁平事務不足以支援的例子。例如使用者在旅行網站上進行自己的旅行度假計劃,使用者設想從杭州到義大利的佛羅倫薩,這兩個城市沒有直達的班機,需要使用者預訂並轉呈航班,需要或者搭火車等待。使用者預訂旅行度假的事務為
BEGIN WORK:
S1:預訂杭州到上海的高鐵
S2:上海浦東國際機場坐飛機,預訂到米蘭的航班
S3:在米蘭轉火車前往佛羅倫薩,預訂去佛羅倫薩的火車
但是當用戶執行到S3時,發現由於飛機到達米蘭的時間太晚,已經沒有當天的火車,這時使用者希望在米蘭當地住一晚,第二天出發去佛羅倫薩。這時如果事務為扁平事務,需要回滾之前S1 S2 S3的三個操作,這個代價明顯很大,因為當再次進行該事務是,S1 S2的執行計劃是不變的,也就是說,如果支援有計劃的回滾操作,那麼不需要終止整個事務,因此就出現了帶有儲存點的扁平事務
帶有儲存點的扁平事務 除了支援扁平事務支援的操作外,允許在事務執行過程中回滾同一事務中較早的一個狀態。這是因為某些事務可能在執行過程中出現的錯誤並不會導致所有的操作都無效,放棄整個事務不合乎要求,開銷太大,儲存點用來通知事務系統應該記住事務當前的狀態,以便當之後發生錯誤時,事務能回到儲存點當時的狀態
對於扁平的事務來說,隱式的設定了一個儲存點。然而整個事務中,只有這一個儲存點,因此,回滾只能會滾到事務開始時的狀態,儲存點用SAVE WORK函式來建立,通知系統記錄當前的處理狀態。當出現問題時,儲存點能用作內部的重啟動點,根據應用邏輯,決定是回到最近一個儲存點還是其他更早的儲存點。圖顯示了事務中使用的儲存點
顯示瞭如何在事務中使用儲存點,灰色背景部分表示由ROLLBACK WORK而導致部分回滾,實際並沒有執行操作,當用BEGIN WORK開啟一個事務時,隱式地包含了一個儲存點,當事務通過ROLLBACK WORK:2發出部分回滾命令時,事務會滾到儲存點2,接著依次執行,並再次執行到ROLLBACK WORK:7,知道最後COMMIT WORK操作,表示事務結束,除灰色陰影部分的操作外,其餘操作都已經執行,並且提交
另一個需要注意的是,儲存點在事務內部是遞增的,從圖中可以看出,有人可能會想,返回儲存點2以後,下一個儲存點可以為3,因為之前的工作已經終止,然而新的儲存點編號為5,這意味著ROLLBACKU 不影響儲存點的計數,並且單調遞增編號能保持事務執行的整個歷史過程,包括在執行過程中想法的改變
此外,當事務通過ROLLBACK WORK:2命令發出部分回滾命令時,要記住事務並沒有完全被回滾,只是回滾到儲存點2而已,這代表當前事務是活躍的,如果想要回滾事務,還需要執行ROLLBACKUP WORK
鏈事務 可視為儲存點模式的一種變種,帶有儲存點的扁平事務,當發生系統崩潰是,所有的的儲存點都將消失,因為其儲存點是易失的,這意味著當進行恢復時,事務需要從開始處重新執行,而不能從最近的一個儲存點繼續執行
鏈事務的思想是:在提交一個事務時,釋放不需要的資料物件,將必要的處理上下文隱式地傳給下一個要開始的事務,提交事務操作和開始下一個事務操作 將合併為一個原子操作,這意味著下一個事務將看到上一個事務的結果,就好像一個事務中進行的一樣,如圖顯示了鏈事務的工作方式
鏈事務與帶有儲存點的扁平事務不同的是,帶有儲存點的扁平事務能回滾到任意正確的儲存點,而鏈事務中的回滾僅限當前事務,即只能恢復到最近的一個儲存點,對於鎖的處理,兩者也不相同,鎖事務在執行COMMIT後即釋放了當前所持有的鎖,而帶有儲存點的扁平事務不影響迄今為止所持有的鎖
巢狀事務 是一個層次結構框架,由一個頂層事務(top-level transaction)控制著各個層次的事務,頂層事務之下巢狀的事務被稱為子事務,其控制每一個區域性的變換,結構如下
下面給出MOSS對巢狀事務的定義
1 巢狀事務是由若干事務組成的一棵樹,子樹既可以是巢狀事務也可以是扁平事務
2 處在葉節點的事務是扁平事務,但是每個事務從根到葉節點的距離可以說是不同的
3 位於根節點的事務稱為頂層事務,其他稱為自事務。事務的前驅稱(predecessor)為父事務(parent),事務的下一層稱為兒子事務(child)
4 子事務既可以提交也可以回滾。但是它的提交操作並不馬上生效。除非其父事務已經提交。因此可以推論出,任何子事務都在頂層事務提交後才真正的提交
5 樹中的任意事務回滾會引起它的所有子事務一同回滾,故子事務僅保留ACI特性而不具有D特性
在Moss的理論中,實際的工作是交由葉子節點完成,即只有葉子節點的事務才能才能訪問資料庫、傳送資訊、獲取其他型別的資源。而高層的事務僅負責邏輯控制。決定合適呼叫相關的子事務。即使一個系統不支援巢狀事務,使用者也可以通過儲存點技術來模擬巢狀事務,如圖
如圖可以發現,在恢復時採用儲存點技術比巢狀查詢有更大的靈活性。例如在完成Tk3這事務時,可以會滾到儲存點S2的狀態。而在巢狀查詢的層次結構中,這是不被允許的
但是用儲存點技術來模擬巢狀事務在鎖的持有方面還是與巢狀查詢有些區別。當通過儲存點技術來模擬巢狀事務時,使用者無法選擇哪些鎖需要被子事務整合,哪些需要被父事務保留,這就是說,無論有多少個儲存點,所有被鎖住的隊形都可以被得到和訪問。而在巢狀查詢中,不同的子事務在資料庫物件上持有的鎖是不同觀點。例如一個父事務P1 其持有物件X和Y的排他鎖,現在要開始呼叫子事務P11 ,那麼父事務P1 可以不傳遞鎖,也可以傳遞所有的鎖,也可以只傳遞一個排他鎖,如果子事務P11 中還持有物件Z的排他鎖,那麼通過反向繼承(counter-inherited)父事務P1 將持有3個物件X Y Z的排他鎖。如果這時再次呼叫一個子事務P12 ,那麼它可以傳遞哪裡已經持有的鎖
然而,如果系統支援巢狀事務中並行地執行的各個子事務,在這種情況下,採用儲存點的扁平事務來模擬巢狀事務就不切實際了。這從另一個方面反映出,想要實現事務間的並行性,需要真正支援的巢狀事務
分散式事務 通常是一個分散式環境下執行的扁平事務,因此需要根據資料所在位置訪問網路中的不同節點
假如一個使用者在ATM機上進行銀行的轉賬操作,例如持卡人從招商銀行儲存卡轉賬10 000 元到工商銀行的儲存卡。這種情況下,可以將ATM機視為節點A,招商銀行的後臺資料庫視為節點B,工商銀行的後臺資料庫視為C,這個轉賬的操作可分解為以下的步驟
節點A發出轉賬命令
節點B執行儲存卡中的餘額減去10 000
節點C執行儲存卡終端的餘額增加10 000
節點A通知使用者操作完成或者節點A通知使用者操作失敗
這裡需要使用到分散式事務,因為節點A不能通過一臺資料庫就完成任務,其需要訪問網路中兩個節點的資料庫,而在每個節點的資料庫執行的實務操作有都是扁平的,對於分散式事務,其同樣需要滿足ACID特性,要麼都發生,要麼都失敗。對於上述例子,如果2 3 步中任何一個操作失敗,都會導致整個分散式事務回滾,若非這樣,結果非常可怕
對於InnoDB儲存引擎來說,其支援扁平事務,帶儲存點的事務,鏈事務,分散式事務。對於巢狀事務,其原生不支援。因此對有併發事務需求的使用者來說,MySQL資料庫或InnoDB儲存引擎就顯得無能為力,然而使用者仍可以通過帶儲存點的事務來模擬序列的巢狀事務