BT

最新技術を追い求めるデベロッパのための情報コミュニティ

寄稿

Topics

地域を選ぶ

InfoQ ホームページ ニュース JepsenがMongoDBのデータ整合性の主張に異議を唱える

JepsenがMongoDBのデータ整合性の主張に異議を唱える

原文(投稿日:2020/05/22)へのリンク

MongoDBとJepsenというタイトルの記事で、MongoDBは、データベースが「業界で最も厳しいデータの安全性、正確性、一貫性のテスト」に合格したと主張した。これに応えて、Jepsenは、MongoDB 3.6.4が実際にはテストに失敗したことを示す記事を公開した。新しいMongoDB 4.2.6にはより多くの問題があり、トランザクションの順序を逆にして、将来の書き込みの結果を確認できる読み取りの「遡及的トランザクション」などがある。

Jepsen LLCの回答は、公式Twitterフィードでの次のMaxime Beugnet氏への回答から始まる:

そのWebページを見たとき、眉を上げることを認めなければなりません。そのレポートでは、MongoDBはデータを失い、デフォルトで因果関係に違反していました。どういうわけか、それが「今日利用可能なデータベースの中で最も強力なデータの整合性、正確性、および安全性の保証の中で」となりました!

問題のレポートは、Kit Patella氏によってMongoDB 3.6.4というタイトルが付けられた。Kyle Kingsbury氏による新しいレポートは、これを拡張している:

同様に、MongoDBのデフォルトの読み取りレベルは、読み取りの中止が許可されることです。読み取りは、将来破棄される可能性がある、完全にコミットされていない状態を監視できます。読み取り分離の一貫性に関するドキュメントに記載されているように、「コミットされていない読み取り (Read Uncommitted) がデフォルトの分離レベルです」

これらの弱いデフォルトのために、MongoDBの因果関係セッションはデフォルトで因果関係の一貫性を維持していませんでした。ユーザは実際に因果関係の一貫性を得るには、Write と Read の両方の Concern に majority (またはそれ以上) を指定する必要がありました。MongoDBは問題を解決し、設計どおりに機能していると述べ、分離ドキュメントを更新して、MongoDBが「クライアントセッションでの因果的一貫性」を提供していても、ユーザーが Read と Write の両方の Concern に majority を使用するように気をつけない限り、保証は保持されないことに注意しました。詳細な表に、弱い読み取りと書き込みに提供されるプロパティが表示されています。

トランザクション分離の失敗

近年、MongoDBはそのトランザクション機能を大幅に推進している。しかし、Jepsenが発見したように、トランザクションサポートはデフォルトでは機能しない。あるテストでは、トランザクションを使用してドキュメントに値を追加した。彼らは、データベース/コレクションレベルで Write Concern が majority であっても、トランザクションレベルでデフォルトの Write Concern を使用すると、「トランザクションは確認済みの書き込みを失うように見えた」ことを発見した (これは、トランザクションレベルで Write Concern を明示的に指定することで対処できる) 。

クライアントは、[1 2 3 4 5 6 7]まで単調に増加する要素のリストを観察し、その時点でリストは[]にリセットされ、[8]で新たに開始されました。これは、MongoDBのロールバックの例であるかもしれません、これは「データ損失」を表すための凝った言い方です。

これは悪いことに、もっと微妙な疑問が生じます。なぜこれらの値をまったく読み取ることができなかったのでしょうか。結局のところ、Read Concern の linearizable は、majority が承認された書き込みのみ (つまり耐久性のある) を示すことになっています。答えは驚くべきものですが、文書化されています。MongoDBの設計上の選択は次のとおりです:

トランザクションの操作では、トランザクションレベルの Read Concern が使用されます。つまり、コレクションおよびデータベースレベルで設定された Read Concern は、トランザクション内で無視されます。

事実上、これは「明示的な Read Concern がないトランザクションは、データベースまたはコレクションレベルで要求された Read Concern をローカルのデフォルトレベルにダウングレードする」ことを意味し、トランザクションがコミットされていないデータを読み取って、後でロールバックできるようにする。

逆も問題である。ドキュメントによると「トランザクションがコミットに Write Concern「majority」を使用しない場合、Read Concern「snapshot」は、読み取り操作が多数決されたデータのスナップショットを使用することを保証しません」。言い換えると、Read Concern「snapshot」は、Write Concern を設定せずに事実上無視される。また、トランザクションはコレクションおよびデータベースレベルの設定を無視するため、これはトランザクションレベルで実行する必要がある。

遡及的トランザクション

スナップショットアイソレーションを使用しても、予期しない結果をもたらすシナリオが多数あった。それらのほとんどはここで要約するには複雑すぎるが、そのうちの1つは本当に際立っていた。

あるテストで、Jepsenの研究者はクライアントにドキュメントを読んでから値を追加するように指示した。テストの開始時に、ドキュメントにはシーケンス [2、3、4] が含まれていた。値を読み取った後、ドキュメントは [1、2、3、4] に変更された。

これは通常は機能したが、4つのトランザクションで、クライアントはデータベースから [1、2、3、4] を読み取った。Kingsbury氏は続ける、

もちろん、これは不可能です。テストでは、各トランザクションの操作が厳密な順序で送信されます。MongoDBがタイムマシンを構築しない限り、書き込まれるかどうかがまだわからない値を返すことはできません。これは、遡及的トランザクションが実際に2回実行され、2回目の実行で、それ自体の以前の実行の影響が観察されたことを示しています。これは、不適切な再試行メカニズムの別の結果である可能性があります。

再試行メカニズムが非難されたのはこれだけではありません。

ネットワークパーティションにより、MongoDBがトランザクションの効果を複製する可能性があることがわかりました。同じ値を配列に2回追加することはありませんが、同じ要素の複数のコピーを持つ配列を繰り返し観察しました。

これらの動作をよりよく理解するために、研究者は自動再試行を無効にしようとしたが、「MongoDBトランザクションは retryWrites 設定を無視し、関係なく再試行する」ことを発見した。

Jepsenは、MongoDBをより安全に使用する方法について開発者にアドバイスを提供することに加えて、「MongoDBは、「ACID」ではなく「スナップショットアイソレート」を使用するようにマーケティング言語を改訂することを希望したい」と勧めている。

編集注記: この記事の以前のバージョンでは、トランザクションを使用するとデータが常に失われる可能性があることを示唆していた。この特定の問題は、トランザクションの Write Concern に default を使用した場合にのみ発生した。ただし、Write Concern に majority を使用したトランザクションで他の異常が検出された。

この記事に星をつける

おすすめ度
スタイル

特集コンテンツ一覧

BT