快照隔離而非ACID:MongoDB數據一致性能力遭質疑

在一篇題爲“MongoDB和Jepsen”的文章中,MongoDB官方聲稱他們的數據庫通過了“業界最嚴格的數據安全性、正確性和一致性測試”。作爲迴應,Jepsen官方發表了一篇文章,指出MongoDB 3.6.4實際上沒有通過他們的測試,而MongoDB 4.2.6的問題則更多,包括“回溯關聯性事務”(回溯關聯性事務是指事務會反轉操作順序,讓讀操作可以看到未來寫操作的結果)。

Jepsen在官方Twitter上對Maxime Beugnet做出了回覆:

不得不承認,在看到那個網頁時,我大吃一驚。在測試報告中,MongoDB不僅丟失數據,還違背了關聯關係,它怎麼就成爲“當今所有可用數據庫中具有最強大的數據一致性、正確性和安全性保證的數據庫之一呢”!

上述的報告出自Kit Patella的一篇題爲“MongoDB 3.6.4”的文章,而Kyle Kingsbury的新報告對此進行了擴展:

類似地,MongoDB的默認讀選項允許中止讀,即讀操作可以觀察到未完全提交併可能在未來被丟棄的狀態。正如“讀隔離級別一致性”文檔所指出的:“讀未提交是默認的隔離級別”。

我們發現,由於這些默認設置,MongoDB的關聯會話在默認情況下並不會保持關聯一致性:用戶需要同時指定寫操作和讀操作的選項爲“majority”才能獲得關聯一致性。MongoDB關掉了這個問題,說原本就是這樣設計的,並更新了隔離級別文檔,說即便MongoDB提供了“客戶端會話的關聯一致性”,但並不保證,除非用戶小心使用讀操作和寫操作選項。現在,文檔中有一個表格詳細描述了較弱的讀寫關注點屬性。

失敗的事務隔離

近年來,MongoDB一直在大力推廣它的事務能力。但Jepsen發現,在默認情況下MongoDB的事務能力並不奏效。在一次測試中,他們通過事務向文檔中追加數據。他們發現,即使在數據庫/集合級別設置了“majority”寫選項,但在事務級別設置了默認的寫選項,那麼“事務似乎會丟掉已確認的寫操作”(這可以通過在事務級別顯式指定寫選項來解決)。

客戶端看到一個元素單調遞增的列表[1 2 3 4 5 6 7],此時列表重置爲[],並使用[8]重新開始。這可能是MongoDB回滾的一個例子,是“數據丟失”的一種奇特說法。

那麼一個更微妙的問題出現了:爲什麼我們能夠讀到這些值?畢竟,讀選項應該只顯示多數確認的(即持久化的)寫操作。答案有點令人驚訝,文檔中寫提到了MongoDB的設計:
事務中的操作使用的是事務級別的讀選項,也就是說,在集合和數據庫級別設置的任何讀選項在事務內部都會被忽略。

這意味着“沒有顯式聲明讀選項的事務會將數據庫或集合級別的請求讀選項降級爲局部默認級別”,從而允許事務讀取未提交的數據,而這些數據稍後可能會被回滾。

反過來也是有問題的。根據文檔所述,“如果事務沒有對提交的數據使用‘majority’寫選項,“snapshot”讀選項不能保證讀操作使用的是通過‘majority’選項提交的數據的快照”。換句話說,在沒有設置寫選項的情況下,“snapshot”讀選項將被忽略。同樣,這個是發生在事務級別,因爲事務忽略了集合和數據庫級別的設置。

回溯關聯性事務

即使使用快照隔離,也可能會出現很多意外的結果。它們中的大多數都太複雜了,其中有一個很突出。

在一次測試中,Jepsen的研究人員使用客戶端讀取文檔,然後向它追加數據。在測試開始時,文檔包含序列[2,3,4]。讀取數值後,文檔被改爲[1,2,3,4]。

這通常是有效的,但要在四個事務中從數據庫中讀取[1、2、3、4],Kingsbury繼續寫道:

當然,這是不可能的:我們的測試嚴格按照順序提交事務的操作,除非MongoDB有時間機器,否則它不可能返回還沒有被寫入的值。這說明回溯性事務實際上執行了兩次,並且在第二次執行時看到了其自身先前執行的結果。這可能是因爲不恰當的重試機制導致的結果。

這並不是唯一一次重試機制被人們指責。

我們發現,網絡分區可能會導致MongoDB重複執行事務。儘管不會將相同的值追加到一個數組兩次,但我們發現了數組會包含相同元素的多個副本。

爲了更好地理解這些行爲,研究人員試圖禁用自動重試,結果發現“MongoDB事務忽略了retryWrites設置,仍然會重試”。

除了爲開發人員提供如何更安全地使用MongoDB的建議之外,Jepsen還建議“MongoDB修改營銷描述,使用‘快照隔離’而不是‘ACID’”。

編後語:之前的文章暗示在使用事務時總是會發生數據丟失,實際上這個問題只會在使用事務默認寫選項時發生。但是,使用“majority”寫選項的事務也出現了其他異常。

原文鏈接

Jepsen Disputes MongoDB’s Data Consistency Claims

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