「分散式技術專題」事務基礎及特性

Hubble資料庫發表於2023-02-14

事務中的基本概念

在資料庫中,會將有意義的資料操作進行集中處理,利用資料庫進行資料的檢索、插入、更新、刪除操作, 這裡使用者的一個連貫的操作,就是事務 (transaction)。

為瞭解決多個使用者同時訪問資料庫時不會發生問題,就需要控制這些操作, 也就是通常意義上的併發控制中的上鎖( LOCK)操作(樂觀併發不上鎖的情況不在本文討論範圍內)。

上鎖的意義在於防止對重要資料的誤操作。比如兩筆對同一賬戶的轉賬,如果併發操作,可能第二次轉賬未讀取到第一次轉賬後的結果時, 會造成賬戶的金額錯誤。這種情況下,第二次操作不能在第一次操作結束之前進行操作。

當各種事務操作正確完成時,確認對資料庫的處理過程就是提交( COMMIT)。同時,由於資料庫是多人共享資料,非常頻繁的上鎖會導致效能問題, 一般情況下需要根據情況使用鎖。

• 使用者僅進行讀操作時,使用共享鎖,在上共享鎖時,其他使用者能夠讀取資料,但不能寫入。
• 使用者寫操作時,使用獨佔鎖,上獨佔鎖時,其他使用者既不能讀取又不能寫入。
使用鎖控制多個事務執行就被稱之為併發控制( concurreny control)。在使用併發控制後,即使再多的人使用資料庫也不會發生矛盾。

這裡假設有事務 A對於賬戶I上了獨佔鎖,同時事務B對賬戶J上了獨佔鎖,如果這時A想給J上獨佔鎖, B想給I上獨佔鎖時,由於兩個事務都等待對方解除鎖,處理就進行不下去了,這時就產生了死鎖(deadlock), 資料庫中一般都會有預防死鎖的機制的,有的資料庫採用超時機制,持續一段時間以後, 事務會採取取消的方式,取消事務就是資料庫中的回滾(rollback)。為了防止出現安全性問題, 資料庫中事務包含的一系列操作要麼全部成功要麼全部失敗,不允許出現中間狀態。而為了防止發生故障,而導致事務的中斷產生問題,就需要引入事務日誌,在故障恢復後, 讀取事務日誌,對資料庫進行恢復。

事務的性質

由於資料庫的使用者眾多,並且多個資料庫操作同時執行,同時可能發生故障,不允許各事務之間發生影響。因此,資料庫事務應該滿足一些特性,這些特性就是通常稱之為 ACID的特性。
ACID特性如下表所示:
特性
內容
含義
A-Atomicity
原子性
資料庫事務必須結束在提交或回滾
C-Consistency
一致性
執行資料庫事務不能損壞資料庫的一致性
I-Isolation
隔離性
兩個事務執行不能相互干擾,一個事務不能看到其他事務執行時的中間某一時刻的資料
D-Durability
永續性
在事務完成之後,事務對資料庫所做的更改要持久化,將資料儲存在資料庫中,不能被回滾

特性 1—— 原子性
首先,資料庫事務要具備原子性。資料庫事務需要提交或者回滾來結束。提交是確定資料庫事務處理的指令,回滾是取消資料庫事務處理的指令。提交或者回滾可以自動執行,或者顯式執行。顯式執行中,根據是否發生錯誤, 變更資料庫事務處理。一般在資料庫中顯式指令為提交 COMMIT和回滾ROLLBACK。滿足原子性就要求事務的操作序列或者完全應用於資料庫或者完全不影響資料庫。如果使用者完成了提交,這時所有的更新對於外部世界必須完全可見,如果使用者完成了 回滾,要求完全不可見或者說完全沒有影響。

特性 2 ——   一致性
資料庫事務要具備一致性。資料庫執行前後資料庫不存在矛盾。例如, 資料庫賬戶表某賬戶有 1萬,A加1萬,B加1萬,結果不能變成2萬,避免出現更新遺失 (lost update)。並行處理資料庫的事務,多個事務可能同時訪問相同的表或行。此時,根據事務的處理順序不能發生矛盾。即事務對於資料庫中相同的資源的訪問, 不會發生矛盾。併發控制手段有鎖(2PL、3PL),時間戳控制(TO),樂觀控制(OCC)等。

特性 3 —— 隔離性
在資料庫中執行的事務不斷增加,能夠逐漸控制事務之間相互干涉的級別就叫做隔離級別 isolation level)。隔離級別分為下列四個級別:
– READ UNCOMMITTED:允許讀取未提交資料。SQL允許的最低一致性級別。
– READ COMMITTED:只允許讀取已提交,但不要求可重複讀。
– REPEATABLE READ:只允許讀取已提交資料,並且在一個事務兩次讀取一個資料項期間, 其他事務不得更新該資料。
– SERIALIZABLE:保證可序列化排程。
透過設定隔離級別,可能出現三種現象。
– 髒讀(dirty read):指事務1在提交前事務2讀取到了共同訪問的行, 在事務1回滾的情況下,事務2讀取到了不存在的行。
– 非重複讀(non-repeatable read):事務1讀取行時,事務2更新這行並提交時, 事務1再次讀取這行,數值發生不一致的現象。
– 幻讀(phantom):指事務1進行檢索,獲得多行結果,事務2追加了符合該條件的行, 事務1第二次檢索的結果發生不同的現象。
各隔離級別發生現象的表:
特性
髒讀
非重複讀
幻讀
讀取未提交
可能發生
可能發生
可能發生
讀取已提交
不可能
可能發生
可能發生
可重複讀
不可能
不可能
可能發生
可序列化
不可能
不可能
不可能
可見事務級別越高,事務越安全,距離可序列化保證越近,但事務級別越高, 效能是在下降的,所以一般情況下,傳統關係型資料庫預設的事務級別都不是可序列化級別, 可能是讀取已提交,或者類似於這個級別的自定義級別 -快照隔離。
事務的故障恢復概念
在資料庫設計時需要將資料庫故障視為常態,系統發生的故障有很多種。每種故障都需要不同的方法來處理,而事務故障就是在設計事務管理器中首先需要考慮的事情。

一般來說,事務故障可能發生兩種:

• 邏輯錯誤:事務由於某些內部條件而無法繼續正常執行,這些內部條件包括非法輸入、 找不到資料、溢位或超出資源限制。
• 系統錯誤:系統進入一種不良狀態(如死鎖),結果事務無法繼續正常執行。
考慮事務原子性,如透過在事務執行過程中發生了系統崩潰,如果執行中有記憶體的內容, 在崩潰時,無法知道其中事務的內容,系統重啟時就會出現不滿足事務原子性的情況, 可能事務已經完成,可能事務完成一半,可能事務完全沒成功,根本無法確認。
原子性的目標是要麼執行了事務對資料庫的所有修改,要麼都不執行。但是如果事務 執行多處資料庫修改,可能需要多個輸出操作,並且故障可能發生於某些修改完成後 全部修改完成前。
為了達到保持原子性的目標,必須在修改資料庫本身之前,首先向磁碟輸出資訊, 描述要做的修改。這些資訊要確保已經提交事務所做的所有修改都能反映到資料庫, 或者在故障後的恢復過程中反映到資料庫中。這種資訊還有一個好處,就是確保在 中止事務時事務所做的任何修改都不會持久存在於資料庫中。
這裡應用最廣泛的記錄資料庫修改的結構資料就是日誌。日誌記錄資料庫中所有更新活動。
傳統資料庫中的事務日誌方案,日誌記錄有幾種。
採用更新日誌記錄描述一次資料庫寫操作,一般有下列欄位:
• 事務日誌,執行寫操作的事務的唯一標識。
• 資料項標識,是所寫資料項的唯一標識。通常是資料項在磁碟上的位置, 包括資料項所駐留的塊的快標識和塊內偏移量。
• 舊值,資料項的寫前值
• 新值,資料項的寫後值
例如將更新日誌記錄記為 <Ti,Xi,Vo,Vn>
除了更新日誌記錄外,其他的日誌記錄用於記錄事務處理過程中的重要事件, 如事務的開始以及事務的提交或中止。例如:
• 事務開始記為<Ti,start>
• 事務提交記為<Ti,commit>
• 事務中止記為<Ti,abort>
每次事務執行寫操作時,必須在資料庫修改前建立該次寫操作的日誌記錄,並將其加入到日誌中。一個日誌記錄一旦存在,就可以根據需要將修改輸出到資料庫中。並且可以根據日誌, 撤銷已經輸出到資料庫中的修改,也就是利用了更新日誌記錄中的寫前值。
一般將日誌記錄存放在穩定儲存器中,以便在系統故障或磁碟故障時恢復。
資料庫中的 undo和redo,Redo與Undo並非是相互的逆操作,而是能配合起來使用的兩種機制。Redo用來保證事務的原子性和永續性,Undo能保證事務的一致性,兩者也是系統恢復的基礎前提。
• undo使用一個日誌記錄,將該日誌記錄中指明的資料項設定為舊值。
在進行級聯回滾時可將日誌中的讀資料項看做 UNDO型日誌記錄。如果事務在更新資料庫之後但在提交之前,無論由於什麼原因引發故障, 都可能需要對事務進行回滾。如果事務已修改了任何資料項值並寫入資料庫, 必須將它們恢復為原值,使用UNDO型日誌記錄將必須回滾的資料項恢復為其舊值。
• redo使用一個日誌記錄,將該日誌記錄中指明的資料項設定為新值。
redo是在恢復時將所有資料項都更新為新值,所以對於透過redo來執行更新的執行順序很重要, 如果崩潰恢復時,資料項的更新執行順序不同於原來它們的執行順序,那麼該資料項的 最終狀態將是一個錯誤值。大多數的恢復演演算法,都沒有把每個事務的重做分別執行, 而是對日誌進行一次掃描,在掃描過程中,每遇到一個redo日誌記錄,就執行一次redo動作。這種方法能確保保持更新的順序,並且效率更高,因為僅需要整體讀一遍日誌, 而不是對每個事務讀一遍日誌。
還有一種日誌記錄型別是檢查點 (check point),當系統發生故障時,必須檢查日誌, 決定哪些事務需要undo和redo,原則上,需要搜尋整個日誌來確定訊息,但存在兩個問題:

1、搜尋耗時過大。

2、大多說需要重做的事務已將更新寫入資料庫了,儘管進行redo不會存在問題, 但會使恢復過程變得過長。
為了降低這種開銷,需要引入檢查點。系統週期性地把所有被修改的資料庫快取寫入磁碟時, 相應地在日誌中寫入 <checkpoint,L>記錄(L檢查點時活躍的事務列表)。當系統發生崩潰時, 對於日誌中記錄檢查點之前所有具有提交記錄的事務,無需對這些事務的寫操作進行redo, 因為在檢查點之前,它們的所有更新都已經儲存到了磁碟的資料庫中。
檢查點的執行過程:

3、將當前位於主存的所有日誌記錄輸出到儲存。

4、將所有修改的快取塊輸出到儲存。

5、將日誌記錄<checkpoint,L>輸出到儲存。
檢查點引入時:

6、在執行檢查點操作時不允許執行任何更新

7、在執行檢查點過程中將所有更新過的快取都輸出到磁碟。
由於存在以上兩個限制條件,也會引起相當大的麻煩,因為這時,事務處理會出現停頓。所以就出現了模糊檢查點( fuzzy checkpoint),它允許在快取塊正在寫入時也允許事務執行更新。

 

以上為事務基礎及特性, 「分散式技術專題」是國產資料庫 hubble 團隊精心整編,專題會持續更新,歡迎大家保持關注。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70026685/viewspace-2935101/,如需轉載,請註明出處,否則將追究法律責任。

相關文章