資料庫事務原子性 一致性是怎樣實現的?

2021-09-30 20:37:25 字數 2278 閱讀 9972

這個問題的有趣之處,不在於問題本身(「原子性、一致性的實現機制是什麼」),而在於回答者的分歧反映出來的另外乙個問題:原子性和一致性之間的關係是什麼?

我特別關注了@我練功發自真心 的答案,他正確地指出了,為了保證事務操作的原子性,必須實現基於日誌的redo/undo機制。但這個答案仍然是不完整的,因為原子性並不能夠完全保證一致性

按照我個人的理解,在事務處理的acid屬性中,一致性是最基本的屬性,其它的三個屬性都為了保證一致性而存在的。

首先回顧一下一致性的定義。所謂一致性,指的是資料處於一種有意義的狀態,這種狀態是語義上的而不是語法上的。最常見的例子是轉帳。例如從帳戶a轉一筆錢到帳戶b上,如果帳戶a上的錢減少了,而帳戶b上的錢卻沒有增加,那麼我們認為此時資料處於不一致的狀態。

在資料庫實現的場景中,一致性可以分為資料庫外部的一致性和資料庫內部的一致性。前者由外部應用的編碼來保證,即某個應用在執行轉帳的資料庫操作時,必須在同乙個事務內部呼叫對帳戶a和帳戶b的操作。如果在這個層次出現錯誤,這不是資料庫本身能夠解決的,也不屬於我們需要討論的範圍。後者由資料庫來保證,即在同乙個事務內部的一組操作必須全部執行成功(或者全部失敗)。這就是事務處理的原子性。

為了實現原子性,需要通過日誌:將所有對資料的更新操作都寫入日誌,如果乙個事務中的一部分操作已經成功,但以後的操作,由於斷電/系統崩潰/其它的軟硬體錯誤而無法繼續,則通過回溯日誌,將已經執行成功的操作撤銷,從而達到「全部操作失敗」的目的。最常見的場景是,資料庫系統崩潰後重啟,此時資料庫處於不一致的狀態,必須先執行乙個crash recovery的過程:讀取日誌進行redo(重演將所有已經執行成功但尚未寫入到磁碟的操作,保證永續性),再對所有到崩潰時尚未成功提交的事務進行undo(撤銷所有執行了一部分但尚未提交的操作,保證原子性)。crash recovery結束後,資料庫恢復到一致性狀態,可以繼續被使用。

日誌的管理和重演是資料庫實現中最複雜的部分之一。如果涉及到並行處理和分布式系統(日誌的複製和重演是資料庫高可用性的基礎),會比上述場景還要複雜得多。

但是,原子性並不能完全保證一致性。在多個事務並行進行的情況下,即使保證了每乙個事務的原子性,仍然可能導致資料不一致的結果。例如,事務1需要將100元轉入帳號a:先讀取帳號a的值,然後在這個值上加上100。但是,在這兩個操作之間,另乙個事務2修改了帳號a的值,為它增加了100元。那麼最後的結果應該是a增加了200元。但事實上, 事務1最終完成後,帳號a只增加了100元,因為事務2的修改結果被事務1覆蓋掉了。

為了保證併發情況下的一致性,引入了隔離性,即保證每乙個事務能夠看到的資料總是一致的,就好象其它併發事務並不存在一樣。用術語來說,就是多個事務併發執行後的狀態,和它們序列執行後的狀態是等價的。怎樣實現隔離性,已經有很多人回答過了,原則上無非是兩種型別的鎖:

一種是悲觀鎖,即當前事務將所有涉及操作的物件加鎖,操作完成後釋放給其它物件使用。為了盡可能提高效能,發明了各種粒度(資料庫級/表級/行級……)/各種性質(共享鎖/排他鎖/共享意向鎖/排他意向鎖/共享排他意向鎖……)的鎖。為了解決死鎖問題,又發明了兩階段鎖協議/死鎖檢測等一系列的技術。

一種是樂觀鎖,即不同的事務可以同時看到同一物件(一般是資料行)的不同歷史版本。如果有兩個事務同時修改了同一資料行,那麼在較晚的事務提交時進行衝突檢測。實現也有兩種,一種是通過日誌undo的方式來獲取資料行的歷史版本,一種是簡單地在記憶體中儲存同一資料行的多個歷史版本,通過時間戳來區分。

鎖也是資料庫實現中最複雜的部分之一。同樣,如果涉及到分布式系統(分布式鎖和兩階段提交是分布式事務的基礎),會比上述場景還要複雜得多。

@我練功發自真心 提到,其他回答者說的其實是作業系統對atomic的理解,即併發控制。我不能完全同意這一點。資料庫有自己的併發控制和鎖問題,雖然在原理上和作業系統中的概念非常類似,但是並不是同乙個層次上的東西。資料庫中的鎖,在粒度/型別/實現方式上和作業系統中的鎖都完全不同。作業系統中的鎖,在資料庫實現中稱為latch(一般譯為閂)。其他回答者回答的其實是「在並行事務處理的情況下怎樣保證資料的一致性」。

最後回到原來的問題(「原子性、一致性的實現機制是什麼」)。我手頭有本database system concepts(4ed,有點老了),在第15章的開頭簡明地介紹了acid的概念及其關係。如果你想從概念上了解其實現,把這本書的相關章節讀完應該能大概明白。如果你想從實踐上了解其實現,可以找innodb這樣的開源引擎的源**來讀。不過,即使是乙個非常粗糙的開源實現(不考慮太複雜的並行處理,不考慮分布式系統,不考慮針對作業系統和硬體的優化之類),要基本搞明白恐怕也不是一兩年的事。

資料庫事務原子性 一致性是怎樣實現的?

atomicity consistency 資料庫的一致性依賴於其他三種特性 原子性,隔離性,永續性 原子性用於保證事務中的語句要麼全部執行要麼全部不執行 隔離性用於保證多事務併發處理下事務處理順序與結果的保證 隔離性的處理分為四個級別 atomicity innodb使用undo log 回滾日誌...

oracle事務一致性 原子性

事務的動作要麼一起成功,要麼都不成功,這是事務的原子性。原子性包括 語句級原子性 過程級原子性 事務級原子性 ddl與原子性 如果某條語句 如insert update 執行成功與否會自動控制事務。如設定插入前的觸發器。create table t2 cnt int insert into t2 v...

理解事務 原子性 一致性 隔離性

事務是指對系統進行的一組操作,為了保證系統的完整性,事務需要具有acid特性,具體如下 1.原子性 atomic 乙個事務包含多個操作,這些操作要麼全部執行,要麼全都不執行。實現事務的原子性,要支援回滾操作,在某個操作失敗後,回滾到事務執行之前的狀態。回滾實際上是乙個比較高層抽象的概念,大多數db在...