COSCon'19 | 如何設計新一代的圖數據庫 Nebula
608
2025-04-01
文章目錄
介紹
Atomicity(原子性)
Consistency(一致性)
Isolation(隔離性)
Durability(持久性)
挑戰
隔離級別
異常現象
Dirty read(臟讀)
Non-repeatable read(不可重復讀)
Phantom read(幻讀)
其它異常現象
默認隔離級別
總結
介紹
事務在當今的企業系統中無處不在,在高度并發的環境中也可以提供數據一致性。因此,讓我們首先了解相關的名詞以及在什么樣的場景使用它。
事務是讀/寫操作的集合,僅當所有包含的操作都成功時才成功。
事務具有四個特性(通常稱為ACID):
Atomicity(原子性)
Consistency(一致性)
Isolation(隔離性)
Durability(持久性)
在關系數據庫中,每個SQL語句必須在事務范圍內執行。在不顯式定義事務范圍的情況下,數據庫將使用隱式事務,隱式事務環繞每個單獨的語句。隱式事務在語句執行之前開始,在語句執行之后結束(提交或回滾)。隱式事務模式通常稱為自動提交。
對于企業應用程序,通常會希望避免使用自動提交模式,因為它會嚴重影響性能,并且不允許你在單個原子工作單元中包含多個DML操作。
Atomicity(原子性)
原子性把單個操作作為一個整體并將其轉變為全部成功或全部失敗的單元,只有當所有包含的操作都成功時,該操作才能成功。
事務可能封裝狀態的更改(除非它是只讀)。無論在任何給定時間有多少個并發事務,必須使系統始終保持狀態一致。
Consistency(一致性)
一致性意味著對每個已提交的事務強制執行一致性約束。也就是說所有鍵,數據類型,檢查和觸發器均成功,并且不會觸發任何一致性沖突。
Isolation(隔離性)
事務需要并發控制機制,即使在被交錯時也能保證正確性。隔離給我們帶來的好處是隔離未提交的事務更改狀態,失敗的事務永遠都不會影響當前事務的狀態。通過使用悲觀鎖或樂觀鎖機制的并發控制來實現隔離。
Durability(持久性)
成功的事務必須永久更改系統的狀態,并且在系統停止之前,將狀態更改記錄在持久事務日志中。如果突然系統崩潰或斷電,那么所有未完成的已提交事務都可能會被重放。
對于JMS這樣的消息傳遞系統,事務不是強制性的。這就是我們擁有無事務確認模式的原因。
文件系統操作通常是無事務管理的,但是如果你的業務需求需要對文件進行事務操作,則可以使用XADisk之類的工具。
盡管消息傳遞和文件系統可選擇性地使用事務,但是對于數據庫管理系統,事務是強制性。
挑戰
ACID是一個久遠的說法。吉姆·格雷(Jim Gray)在我出生之前就已經描述了原子性,一致性和持久性。但是那篇論文沒有提到隔離性。如果我們想到70年代后期的數據庫管理系統,這是可以理解的,吉姆·格雷說:
“目前,最大的航空公司和銀行在任何時刻都有大約10,000個操作和大約100個活躍的事務”。
因此,主要的付出都花在保證交付正確性上,而不是并發上。從那個時候到現在,情況發生了翻天覆地的變化,如今,即使是較低的設置也有1000 TPS。
從數據庫的角度來看,原子性是固定屬性,但是出于性能/可伸縮性的考慮,其它的特性都需要權衡。
如果數據庫系統由多個節點組成,則分布式系統一致性(CAP定理中的C,而不是ACID中的C)要求將所有更改都同步到所有節點(多主從復制)。如果副本節點是異步更新的,那么我們將違反一致性規則,系統將“最終保持一致”。
彼得·貝利斯(Peter Bailis)的一篇很好的文章解釋了CAP定理中的一致性和ACID中的一致性之間的區別。
事務是數據狀態轉換,因此即使所有事務同時執行,系統也必須像所有事務都是以串行形式發生一樣進行操作。
如果始終只有一個連接運行,那么串行將不會增加任何并發控制成本。實際上,所有事務系統都必須兼容并發請求,因此序列化會影響可伸縮性。阿姆達爾定律描述了串行執行與并發之間的關系:
“在并行計算中使用多個處理器的程序的速度受到程序順序部分所需時間的限制。”
稍后你將看到,大多數數據庫管理系統都選擇(默認情況下)放寬數據正確性的要求,以實現更好的并發性。
如果企業系統業務需求不要求持久性事務,那么對于高性能集群數據庫來說,持久性發揮作用才有意義。但是,大多數情況下,持久性最好保持不變。
隔離級別
盡管某些數據庫管理系統提供了MVCC,但通常并發控制是通過鎖來實現的。但是眾所周知,鎖會增加執行代碼的可序列化部分,從而影響并行效率。
SQL標準定義了四個隔離級別:
讀取未提交(READ_UNCOMMITTED)
讀取已提交(READ_COMMITTED)
可重復讀(REPEATABLE_READ)
串行化(Serializable)
除串行化級別外,其他所有級別都可能受到數據異常的影響,不同級別可能發生的數據異常現象如下:
異常現象
但是,我們剛剛列出的所有異常現象是什么?我們對每一個進行討論。
Dirty read(臟讀)
當允許事務讀取其他正在運行的事務的未提交更改時,就會發生臟讀。發生這種情況是因為沒有鎖阻止它。在上圖中,您可以看到第二個事務使用了不一致的值,因為第一個事務已回滾。
有關“臟讀”異常的更多信息,請查看這篇文章。
Non-repeatable read(不可重復讀)
所謂不可重復讀,由于并發事務剛剛更新了我們正在讀取的記錄,因此連續讀取產生不同的結果。這是我們不想要的,因為最終使用了過時的數據。通過在當前事務的整個持續時間內在讀取記錄上保留一個共享鎖(讀鎖),可以防止這種情況。
有關不可重復讀取異常的更多信息,請查看這篇文章。
Phantom read(幻讀)
當后續的事務插入了數據,剛好插入的數據又能被并行的事務先前的查詢查到,就會發生幻讀。因此,我們最終將使用過時的數據,這可能會影響我們的業務運行。使用范圍鎖或謂詞鎖可以防止這種情況。
有關幻讀異常的更多信息,請查看這篇文章。
其它異常現象
即使在SQL標準中未提及,你也應注意其它的現象,例如:
丟失更新
讀取偏差
寫入偏差
知道何時會發生這些現象就可以正確地解決它們,這就是數據完整性的全部意義所在。
默認隔離級別
即使SQL標準要求使用SERIALIZABLE隔離級別,但大多數數據庫管理系統使用不同的默認級別。
總結
通常,READ COMMITTED是合適的選擇,因為即使SERIALIZABLE都不能保護你免受丟 失更新的影響,在更新丟失的情況下,讀/寫發生在不同的事務(和Web請求)中。你應該考慮你的系統要求,并進行測試以確定哪個隔離級別最適合你的需求。
數據庫 項目管理 ProjectMan
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。