可串行性與“嚴格”可串行化區別

可串行性與“嚴格”可串行化區別

多年來,“可串行化/序列化”(serializability)被稱爲數據庫隔離級別的“ 黃金標準 ”。它是絕大多數商業數據庫系統中提供的最高隔離級別,一些高度廣泛部署的系統甚至無法提供隔離級別與可序列化一樣高。

在這篇文章中,我們展示了可序列化的可行性,並且說明它從未成爲數據庫系統的“黃金標準”。事實上,嚴格的可串行化才一直是黃金標準。正如我們將看到的,因爲在遺留數據庫系統中實現可串行化提供了關鍵的嚴格保證,所以“可串行化”和“嚴格可串行化”之間的區別大多被忽略了。然而,在以云爲中心的分佈式系統的現代世界中,這種差異是顯著的。

這篇文章首先解釋了數據庫系統中隔離的概念,然後說明了這兩個隔離級別之間的重要差異,以及應用程序員需要注意的“僅僅”引入可串行化系統導致的正確性bug。

背景:什麼是“隔離”

假設我們有一個售票應用程序,允許人們購買限量供應活動的門票。應用程序將以下形式的事務發送到數據存儲(當客戶嘗試買票時):

如果庫存> 0那麼
     庫存=庫存-1; 
     過程(順序)
     返回成功
否則 
     返回失敗FAIL

如果數據存儲支持ACID事務,則將以原子方式處理上述代碼: 將處理整個訂單並減少庫存,或者訂單與庫存兩者都不處理。要麼全部處理要麼全部失敗,除此以外其他任何事情都不可能發生。

如果系統中只運行一個事務,則顯然運行上述代碼不會出現任何問題。如果庫存足夠,則會處理訂單。否則,它不會。

問題通常僅在併發下發生:多個客戶嘗試同時購買一張票。如果有更多客戶試圖購買門票而不是庫存,理想的最終結果是所有庫存都將被出售,而不是更多。

如果允許上述代碼在沒有系統級保證的情況下運行,則代碼中存在明顯的“競爭條件”。兩個並行線程可以同時運行第一行,並且都看到庫存爲“1”。因此,兩個線程都通過IF條件並處理訂單,這導致庫存超賣的負面結果。

系統級保證在面對併發請求時防止這些負面結果屬於ACID的I - “隔離”。

隔離的黃金標準是“可串行化serializability”。保證可串行化的系統能夠同時處理事務,但保證最終結果等同於單獨處理每個事務時發生的事情,一個接一個地處理(串行就好像沒有併發)。這是一個非常強大的保證,它能夠經受住時間的考驗(50年),從而能夠在其上構建健壯且無錯誤的應用程序。

可串行化隔離如此強大的原因是應用程序開發人員根本不需要推理併發性。開發人員只需單獨地關注單個事務的邏輯正確性即可。只要每個單獨的事務不能違反應用程序的語義,開發人員就可以確保同時運行其中許多事務也不會違反應用程序的語義。在我們的示例中,我們只需要確保上面顯示的6行代碼的正確性。只要在數據庫的任何啓動狀態下處理它們時它們都是正確的,那麼應用程序在併發時將保持正確。

可串行化的髒數據祕密:它看起來並不像“安全”

儘管具有令人難以置信的可串行化能力,但確實存在更強的保證,並且保證“僅僅”依靠可串行化的數據庫實際上容易出現與併發性相關的其他類型的錯誤。

可串行化的第一個限制是:它不限制如何選擇等效的事務序列順序。指定一組併發執行的事務,系統保證它們將被等效地處理爲串行順序,但它不保證任何特定的串行順序。

結果,指定一組相同的併發事務處理的兩個副本可能最終處於非常不同的最終狀態,因爲他們選擇以不同的等效序列順序處理事務。因此,“僅僅”依靠可序列化的數據庫的複製不能只複製輸入並讓每個複製事務進程同時處理輸入就可以了,這不能保證複製。

相反,一個複製的進程必須首先處理工作負載,然後處理來自原初始進程發生的一系列狀態改變的複製,這個狀態改變的複製是原初始進程通過網絡發佈的,因此,數據經過網絡延遲到達時間和原始進程中原始數據發生的時間有滯後性。

可串行化的第二個限制是:可序列化系統選擇的等同序列順序不必與提交給系統的事務的順序相關,。在“事務X之後提交的事務Y“與“Y在在X之前處理”是符合等效序列順序的。

即使在X完成後的幾周內提交了Y,這也是正確的 , 理論上可以爲可串行化系統帶來Y及時返回,並在X存在之前處理系統狀態(只要沒有提交的事務讀取Y寫入的相同數據),從技術上講每個只讀事務都可以返回空集(即數據庫的初始狀態),並且不會違反串行化保證,這是合法的,因爲系統可以使只讀事務“及時”返回,並在寫入數據B的任何事務之前以串行順序獲得一個卡位。

任何用戶都不太可能使用始終爲每個只讀查詢返回空集的數據庫。那麼可串行化如何成爲“黃金標準”?

在過去,數據庫只能在一臺機器上運行。因此,數據庫系統保證隔離級別保證更強一致性要超過可串行化serializability。事實上,以至於多年來沒有人爲這個強大的隔離保證保證(即使幾乎每個數據庫系統都保證它)。隔離級別最終被Herlihy和Wing命名爲: 嚴格可串行化。

嚴格的可串行性更安全

嚴格的可串行化在普通可串行化之上添加了一個簡單的額外約束。如果事務Y在事務X完成後啓動(請注意,這意味着X和Y根據定義不是併發的),那麼保證嚴格可串行化的系統保證:

(1)最終狀態等同於按順序處理事務和

(2)X必須在該序列順序中的Y之前。

因此,如果我要向保證嚴格可串行化的系統提交事務,我知道該事務的任何讀取都將反映由於已提交的事務(至少)到達我的事務處理時的數據庫的狀態。提交。事務可能看不到同時提交的事務的寫入,但至少它會看到在它開始之前完成的所有寫入。

當數據庫位於一臺機器上時,保證嚴格的可串行化通常不會增加相對於普通可串行化的工作量。在進行交易之前,每個現有系統(一個例外是Daniel Abadi博士的2014年“懶惰交易”論文)必須執行該交易事務中涉及的寫入。對於稍後出現的事務,忽略這些寫入(而不是看到它們)通常比看到它們更多的工作。因此,幾乎每個在一臺機器上運行的可序列化系統也保證了嚴格的可串行化。這導致了行業現狀,數據庫系統的文檔表明它們保證了“可串行性”,但實際上,它們保證了“嚴格的可串行性”。

“嚴格的可串行化”保證消除了系統返回我們在上一節中討論過的陳舊/空數據的可能性。[但是,它沒有消除我們在該部分討論過的副本分歧問題。我們將在以後的帖子中回到這個問題。]

總結到目前爲止:實際上,“嚴格可串行化”是數據庫系統中的黃金標準隔離級別。但是,只要大多數數據庫在一臺機器上運行,在保證“可串行化”的系統和保證“嚴格可串行化”的系統中沒有可察覺的差異。因此,通俗地說,“可串行化”被稱爲黃金標準,這種口語化的語義不準確性從未如此重要。

分佈式系統使可串行性變得危險

在分佈式系統中,從可串行化到嚴格可串行化的跳躍不再是微不足道的。

以我們的售票應用程序的簡單示例爲例:

假設票證庫存在兩臺機器上覆制 --A和B ----兩者都允許處理交易。客戶向機器A發出減少庫存的事務。此事務完成後,將向計算機B發出另一個事務,以讀取當前庫存。在一臺機器上,第二個事務肯定會讀取第一個事務的寫入。但是現在他們在不同的機器上運行,如果系統不能保證一致的讀取跨機器,第二個事務很可能會返回一個陳舊的髒值(例如,如果複製是異步的,並且第一個事務的寫入尚未從A複製到B,則可能會發生這種情況)。這種陳舊的讀取不會違反可串行化。它相當於第一個事務之前的第二個事務的序列順序。但是,由於第二次交易事務是在第一次交易完成後提交的,因此肯定違反了嚴格的可串行性。

因此,當跨機器複製數據時,可串行化和嚴格的可串行化之間存在巨大而實際的差異。在選擇要使用的數據庫系統之前,最終用戶必須意識到這種差異。無法保證嚴格可序列化的分佈式系統容易出現許多不同類型的錯誤。​​​​​​​

可序列化和嚴格可序列化之間的區別遠遠超過我之前示例中的“陳舊讀取”錯誤。讓我們看看可能出現的另一個錯誤,稱爲“因果反轉”。

如果您存入的金額(在您的所有賬戶中)超過5000美元,銀行會“free checking免費檢查”。愛麗絲正好5000美元,需要給孩子的保姆簽發支票,所以她將一些額外的錢轉入她的儲蓄賬戶。在確認轉移成功並且錢存入她的儲蓄賬戶後,她從她的支票賬戶中提取支票。當她看大結果時,她發現因爲沒有在5000美元以上的賬戶中保持平衡而受到的處罰。

所以發生了什麼事?違反嚴格的可串行性。兩個交易—她的儲蓄賬戶的增加和她的支票賬戶的扣除被重新排序,以便在儲蓄賬戶添加之前發生支票賬戶扣除,即在加法完成之後提交減法。在僅保證普通可串行化的系統中,這種重新排序是完全可能的,但在保證嚴格可串行化的系統中是不可能的。在這種類型的示例中,這種事務重新排序是非常常見的,其中如果不相交的數據位於分佈式系統中的不同機器上,則事務訪問不相交的數據(檢查餘額與儲蓄餘額)。交易事務重新排序後,Alice在兩個賬戶的餘額暫時低於5000美元,這導致了處罰。如果銀行在一個保證嚴格可串行化的系統之上構建他們的應用程序,他們將不必處理來自Alice的憤怒投訴電話。

轉自

揭露數據庫隔離級別的骯髒祕密:可串行性與“嚴格”可串行化區別! - Matt Freels

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章