梁老師小課堂 談談資料庫的事務ACID

2021-10-10 01:42:04 字數 2140 閱讀 6889

在資料庫中新建乙個字段並且設定為索引列,還有刪除整張表的資料,類似這些操作都是一系列操作的組合,執行後不能出現中間狀態,也就是不會出現新建了字段卻不是索引的情況,也不會出現只有一部分資料被刪除的情況。這種保證是事務在發揮作用,雖然我們沒有使用begin-transaction-commit來執行命令。

既然事務是一系列操作的組合,那兩個事務的多個操作如何正確順序執行和如何高效執行就是關鍵了。這就要說說事務的acid原則了,acid指的是原子性、一致性、隔離性、永續性。

假設有這麼乙個場景,使用者a的初始餘額是100元,使用者b的初始餘額是0元,使用者a需要向使用者b轉賬100元。這個場景事實上是分二步執行的,第一步是扣除使用者a賬號上的100元,第二步是給使用者b賬號的餘額增加100元。最終狀態是使用者a餘額為0元,使用者b的餘額為100元。

不過,在執行扣除和增加這兩步時隨時可能發生錯誤。比如業務屬性不匹配,使用者b的賬號有敏感操作被凍結了,無法更新,所以要恢復到初始狀態。又比如系統崩潰了,所以系統重啟時要首先進入安全模式,已提交的事務要繼續完成,未提交的事務要取消掉。這樣才能保證事務操作要麼全部成功,要麼全部失敗。

那如何恢復到初始狀態或者取消未提交的事務呢?

執行操作前把之前的值備份下來,不就可以借助備份進行遞向操作了嘛?沒錯,在資料庫的體現就是undo log回滾段。

前面描述的事務場景可能過於簡單,我們考慮這麼一件事,使用者c在剛才的事務執行過程中給使用者b成功轉入了300元,也就是說同時有多個事務在執行。不幸的是,剛才的事務被回滾了,使用者b的餘額最終被更新成了0元。後果就是使用者c的轉入操作好像沒發生過一樣,成了一筆壞賬。

這個問題的原因是原子性不能保證可見性,當前事務看不到其它事務提交的結果,這才導致了資料的不一致。事實上可以使用排它鎖來保證一致性。對賬號a和賬號b這兩個資源進行加鎖,事務獲得鎖才能執行,執行完才釋放鎖。這樣事務是序列化執行的,當前事務肯定是能看到前乙個事務提交結果的,資料一定是強一致性的。

使用到鎖就要考慮死鎖問題了,死鎖問題說的是兩個程序在不同方向搶占相同的共享資源。我們可以通過碰撞檢測來發現系統中是否存在死鎖,每個程序都記錄已擁有和等待中的鎖,如果出現了回環,說明有死鎖。解決死鎖的一般辦法是鎖等待超時。

使用鎖時除了死鎖還要考慮效能問題,排它鎖是簡單粗暴的方法,但是效能有點不忍直視。這時就得考慮一些優化策略了,比如減少鎖的覆蓋範圍、減少鎖的持有時間、使用並行代替序列。

資料庫的設計大師正是考慮到這些,才引入了事務隔離性。

第一種事務隔離性是序列化讀寫。所有的事務放入到佇列中依次執行,比如讀寫-寫讀-讀讀-寫寫。

第二種是讀已提交。當前事務只能讀取到其他事務已提交的結果,這種隔離下讀-讀、讀-寫都是可以並行執行的,因為當前事務讀取的資料是寫操作的結果。

第三種是可重複讀。在同乙個事務中,多次讀取到的結果是一致的。這種隔離下讀-讀、讀-寫都是可以並行執行的。

第四種是讀未提交。當前事務能看到其他事務還沒有提交的中間狀態,這種隔離下,只有寫鎖,讀是不加鎖的,所以除了寫-寫,讀-寫、寫-讀、讀-讀都是可以並行的。代價是出現髒讀。

透過這四種事務隔離,明顯能看到讀寫鎖帶來的收益,那能不能再優化下呢?

答案是可以的,秘決就是多版本併發控制mvcc,它的本質是寫時複製copy on write。行記錄每次修改時都會產生乙個快照和乙個版本號,版本號是單向增長的邏輯時間戳,用來表示先後順序。而讀操作只會讀取到早於當前事務版本的記錄。顯然,這種技巧非常適合讀多寫少的場景,而且能達到讀未提交的併發度,隔離級別更好。

既然讀-寫、寫-讀、讀-讀都是可以並行的,寫-寫也能並行就更好了。

我們先來看下寫-寫並行會有什麼問題。假設使用者a要給使用者b轉賬100元,使用者b也要給使用者a轉賬100元,考慮到事務間原子操作順序的不可見性,使用者a的餘額可能會在原來基礎上增加了100元,銀行得損失100元。針對這種情況,需要借助樂觀鎖的思想來保證資料的一致性,針對同一行記錄,只有高版本的事務更新能成功,低版本的事務更新得回滾掉。缺點是併發高時失敗率高,需要不斷重試。

除了事務隔離,資料庫設計的大師為了提高併發效率,還做了很多優化。比如每次寫操作並不直接持久化到磁碟中,而是暫時存放在易丟失的記憶體中,然後通過一定的機制非同步同步到磁碟。這樣就保證了資料的永續性,確保事務一旦提交,操作肯定會固化到資料庫中。類似生活中這種場景,餐館老闆娘很忙的時候,就把每筆交易寫在黑板上,當老闆娘空閒、黑板寫滿或者餐館打烊後再整理寫入到賬本中。

談談資料庫事務

首先事務用一句簡單的話來說,事務就是邏輯上的操作,要麼都執行要麼都不執行。如最常見的轉賬。那麼事務是如何來保證這種操作的呢?一 事務的acid 原子性 事務視為乙個整體要麼全部成功要麼全部失敗。以轉賬為例子 在事務中的扣款和價款兩條語句。在資料庫管理系統中,預設情況下一條sql就是乙個單獨的事務,事...

趙渝強老師 資料庫的事務

一 什麼是事務?資料庫事務 transaction 是訪問並可能操作各種資料項的乙個資料庫操作序列,這些操作要麼全部執行,要麼全部不執行,是乙個不可分割的工作單位。事務由事務開始與事務結束之間執行的全部資料庫操作組成。例如 從a賬號給b賬號轉帳,對應於如下兩條sql語句 update from ac...

對資料庫事務的小總結

作為單個邏輯工作單元執行的一系列操作,要麼全都執行,要麼全都不執行。而乙個邏輯工作單元要成為事務,必須滿足acid特性。a atomicity 原子性 事務中的特性要麼不做,要麼全做。c consistency 一致性 事務執行的結果必須是從資料庫從乙個一致性狀態轉換到另乙個一致性狀態。i isol...