以下を提供するシステムがあるとします。
このシステムは serializable と見なされますか?
から スナップショット分離
書き込みスキュー異常では、2つのトランザクション(T1とT2)が重複するデータセット(例:値V1とV2)を同時に読み取り、同時に分離した更新(例:T1更新V1、T2更新V2)を行い、最後に同時にコミットします。他が実行する更新。システムがシリアル化可能である場合、T1またはT2のいずれかが「最初に」発生し、もう一方から見える必要があるため、このような異常は不可能です。対照的に、スナップショット分離では、書き込みスキューの異常が許可されます。
具体的な例として、V1とV2が一人のPhilが保持する2つの天びんであるとします。銀行は、V1またはV2のどちらかが赤字になることを許可します。ただし、両方に保持される合計が負になることはありません(つまり、V1 + V2≥0)。現在、両方の残高は100ドルです。 Philは2つのトランザクションを同時に開始します。T1はV1から$ 200を引き出し、T2はV2から$ 200を引き出します。
これに基づいて、write skewの可能性があることが、スナップショット分離がシリアル化可能でないことを保証するシステムの唯一の理由であると思われます。
ただし、トランザクションが複数のオブジェクトにまたがることを許可しないシステム(上記の例ではV1とV2)では、write skewが発生する。
したがって、上記のシステムはシリアライズ可能です。これは正しいです?
いいえ、私はあなたの規定がシリアル化可能と見なすべきシステムをもたらすとは思いません。
スナップショット分離は、トランザクション全体でトランザクションが同じデータセットを参照できるようにする手法です。スナップショット分離はいくつかの保証を提供しますが、トランザクションが実際にどのように機能するかを理解するために必要なすべての特性を定義しているわけではありません(スナップショット分離とMVCCを融合することを選択しない限り)。
スナップショット分離は、MVCC、マルチバージョン整合性制御を使用して最も一般的に実装されます。 MVCCは、スナップショットのコンテキストでトランザクションの詳細を定義します。書き込みが競合する場合にのみ分離が必要であると言われています(場所のみ、または場所+値。実装によって異なります)。 MVCCは緩和された一貫性モデルを提供し、書き込みスキューに悩まされます。
緩やかな整合性モデルは、分離なしと完全分離のハイブリッドのようなものであるため、理解するのが困難です。
それでは、まず厳密な並行性モデルから始めましょう。一方が他方のデータに書き込む場合、2つのトランザクションは互いに分離する必要があります読み取りまたは書き込み(およびその逆...)。
トランザクションがデータを読み取る理由がわからない場合は、読み取った別の値が関連するクライアントの動作を変更する可能性があると想定する必要があります。これが、トランザクションのオーバーラップの状態が分離を示す理由です。分離しないと、スナップショットで古いデータを読み取ると、緩やかな整合性を簡単に示す可能性があります。これは、不整合、つまりエラーを別の用語で表しています。
トランザクションによって読み取られた、または書き込まれた正確なデータのみを考慮する必要があります。そのセット外のデータを考慮する必要はありません。ただし、トランザクションによって読み取られるデータについて話しているときは、必ずすべての「メタ」データ(および制約のチェックなどのメタ操作によって読み取られるデータとメタデータ)を含める必要があることを理解することが重要です。メタデータの例は次のとおりです。/メタ操作は次のとおりです。一意の新しい主キーの識別。もう1つは列全体の合計です。もう1つは、何かを検索して見つけるのではありません。範囲検索または合計。これは、重複の防止に関する@Matthewのコメントと、@ Tersosaurosの回答に行きます。
たとえば、これは、キー制約のチェックは主キー列全体の読み取りと同義であるため、2つのトランザクションが両方とも行を挿入するとき(一意の主キー制約を想定)に重複する(分離が必要)ことを意味します。別の例として、何かを検索して見つけるのは、その1つの値を読み取るのと同じですが、見つけるのではなく、列のすべての値を調べるのと同じです。
MVCCは、重複または競合する書き込みからのみ保護しますが、読み取りからは保護しません(そのトランザクションによっても書き込まれない限り)。したがって、MVCCで一貫性エラーを取得するために必要なのは、他のトランザクションによって変更されたものを読み取ることです(他のトランザクションは前者のスナップショットが取得された後、最初にコミットされます)一方で、他のトランザクションは古いデータを使用し続け、は、最新のデータと比較して、古いデータに基づいて異なる決定を行います。思ったより簡単に起こします。
整合性の緩和は、一貫性がない、またはエラーが発生しやすいという別の言い方です。 (緩やかな整合性と最終的な整合性を混同しないようにしてください。これは、「NoSQL」から発生しやすいエラーの別の一般的な形式です。)
質問で、トランザクションが複数のオブジェクトにまたがることは決してないと言う場合、これは読み取りと書き込みの両方、および整合性チェック、列全体の集計、不在チェック、範囲検索などのメタデータ(およびメタ操作)に適用する必要があります。 。:もしそうなら、今のところとても良いです。
しかしながら...
個々のオブジェクトでスナップショット分離(MVCC)を使用している(つまり、オブジェクトのロックではなく)とのことです。 (あなたはCASについても言及しています。私は比較と交換、およびテストと設定について聞いたことがありますが、チェックと設定については聞いていません。
あなたの質問を書くと、「オブジェクト」には複数のフィールドがあることが示唆されます。それ以外の場合、質問の規定は不要です。
したがって、snapshott'ed/MVCCで処理されるオブジェクトには複数のフィールドがあるため、単一のオブジェクト内にスキューを書き込む傾向があります。 2つのトランザクションが同じオブジェクトを同時に更新する場合、1つが同じオブジェクト上の他の同時トランザクションによって古くなったオブジェクトの値のフィールドを読み取り、知らないまま続行されるため、不整合(別名エラー)が発生する可能性があります。
代わりにオブジェクトロックを使用できます。これにより、別のトランザクションが既に実行中の場合、2つのトランザクション(更新用)が同じオブジェクトを参照することもできなくなります。
MVCCの壊れた書き込みセットのみの比較モデルを使用せずに、スナップショット分離の代替形式を実行できると思います。したがって、(アルゴリズム的に)比較セットを書き込み専用から昇格させて、読み取りセットも含めることができます。次に、同じオブジェクトを更新する2つのトランザクションは書き込みスキューを引き起こしません(後でコミットを試みるトランザクションは中止されるため)。マルチオブジェクトトランザクションを排除することで、MVCCが私たちにもたらすメリットのほとんどをすでに得ているので、これはあなたが説明している問題に対する適切な解決策であると思います。
(読み取りまたは書き込みが行われる正確で具体的なアイテム/フィールドのみを考慮する必要がありますが、書き込みスキュー(つまりエラー)を防ぐためにメタ操作中にそれらをメタデータとして含める必要があります。比較セットから読み取りセットを削除した場合、またはメタデータ(メタ操作で使用される可能性がある)の考慮に失敗した場合、エラーを許容するモデルがあります。)
@ pjc5 が述べたように、 (強調が追加されました:) 「ifトランザクションが単一のオブジェクトの読み取り/書き込みに制限されている」、「その答えは「はい」です。しかし、これが落ちるのはsingleオブジェクトの考え方にあると思います。
スナップショット分離 の例では、T1とT2は値を共有していません。ただし、「どちらも[他のユーザーが実行した更新を確認していない」ため、書き込みスキューの可能性があります。ソース。したがって、トランザクションを本当に実行するのは、コミットする前に他のすべての更新を確認するのは、トランザクションの機能です。シリアライズ可能。
から シリアライズ可能性 :
スケジュールの直列化可能性とは、同じトランザクションを使用したシリアルスケジュール(つまり、時間的にトランザクションが重複しないシーケンシャル)と(結果として、データベースの状態、データ値が)同等であることを意味します。
残念ながら、このため(そして @ Matthew Mark Miller が指摘するように)、値だけでなくstateも考慮する必要があります。この考慮事項により、 [〜#〜] occ [〜#〜] を使用する2つのトランザクションは、データベースの状態が書き込まれるたびに書き込みスキューが発生する可能性があります 。