208

非反復読み取りとファントム読み取りの違いは何ですか?

Wikipediaの Isolation (database systems) の記事を読みましたが、いくつか疑問があります。以下の例では、何が起こるでしょうか:反復不可能な読み取りファントム読み取り?

取引A
SELECT ID, USERNAME, accountno, amount FROM USERS WHERE ID=1
出力:
1----MIKE------29019892---------5000
取引B
UPDATE USERS SET amount=amount+5000 where ID=1 AND accountno=29019892;
COMMIT;
取引A
SELECT ID, USERNAME, accountno, amount FROM USERS WHERE ID=1

もう 1 つの疑問は、上記の例では、どの分離レベルを使用する必要があるかということです。なぜ?

4

10 に答える 10

214

ウィキペディアから(これには素晴らしい詳細な例があります):

トランザクションの過程で行が2回取得され、行内の値が読み取り間で異なる場合、繰り返し不可能な読み取りが発生します。

ファントム読み取りは、トランザクションの過程で2つの同一のクエリが実行され、2番目のクエリによって返される行のコレクションが最初のクエリと異なる場合に発生します。

簡単な例:

  • ユーザーAは同じクエリを2回実行します。
  • その間に、ユーザーBはトランザクションを実行してコミットします。
  • 繰り返し不可の読み取り:ユーザーAが照会したA行の値が2回目に異なります。
  • ファントム読み取り:クエリ内のすべての行の前後の値は同じですが、異なる行が選択されています(Bが一部を削除または挿入したため)。例:select sum(x) from table;影響を受ける行自体が更新されていない場合でも、行が追加または削除されている場合は、異なる結果が返されます。

上記の例では、どの分離レベルを使用しますか?

必要な分離レベルは、アプリケーションによって異なります。「より良い」分離レベル(同時実行性の低下など)には高いコストがかかります。

この例では、単一の行(主キーで識別される)からのみ選択するため、ファントムの読み取りは行われません。繰り返し不可能な読み取りを行うことができるため、それが問題になる場合は、それを防ぐ分離レベルが必要になる場合があります。Oracleでは、トランザクションAがSELECT FOR UPDATEを発行することもでき、トランザクションBはAが完了するまで行を変更できません。

于 2012-06-15T05:17:37.187 に答える
173

私がそれについて考えるのが好きな簡単な方法は次のとおりです。

繰り返し不可能な読み取りとファントム読み取りの両方は、トランザクションの開始後にコミットされ、トランザクションによって読み取られた、別のトランザクションからのデータ変更操作に関係しています。

繰り返し不可能な読み取りとは、トランザクションがコミットされたUPDATEを別のトランザクションから読み取る場合です。同じ行が、トランザクションが開始されたときとは異なる値になりました。

ファントム読み取りは似ていますが、コミットされたINSERTSおよび/または別のトランザクションからのDELETEから読み取る場合です。トランザクションを開始してから、新しい行または消えた行があります。

ダーティ リードは、繰り返し不可能なファントム リードにていますが、UNCOMMITTED データの読み込みに関連しており、別のトランザクションからの UPDATE、INSERT、または DELETE が読み込まれ、そのトランザクションがまだデータをコミットしていない場合に発生します。「進行中」のデータを読み取っていますが、これは完全ではない可能性があり、実際にはコミットされない可能性があります。

于 2014-04-17T16:41:45.070 に答える
9

これら 2 種類の分離レベルの実装には違いがあります。
「繰り返し不可能な読み取り」の場合、行ロックが必要です。
「ファントム読み取り」の場合は、スコープ ロックが必要です。テーブル ロックも必要です。これら 2 つのレベルは、 2 フェーズ ロックプロトコル
を使用して実装できます。

于 2015-05-18T06:46:58.937 に答える
5

反復不可能な読み取りを行うシステムでは、トランザクション A の 2 番目のクエリの結果にトランザクション B の更新が反映され、新しい金額が表示されます。

ファントム読み取りを許可するシステムで、トランザクション B がID = 1 の新しい行を挿入した場合、トランザクション A は 2 番目のクエリが実行されたときに新しい行を確認します。つまり、ファントム読み取りは、繰り返し不可能な読み取りの特殊なケースです。

于 2012-06-15T04:59:47.877 に答える
2

受け入れられた答えは、何よりも、2つのいわゆる違いが実際にはまったく重要ではないことを示しています.

「行が2回取得され、行内の値が読み取り間で異なる」場合、それらは同じ行ではなく(正しいRDBの話では同じタプルではありません)、定義上、「のコレクション2 番目のクエリによって返される行は、最初のクエリとは異なります。」

「どの分離レベルを使用する必要があるか」という質問に関しては、データがどこかで非常に重要であるほど、Serializable が唯一の合理的な選択肢である可能性が高くなります。

于 2017-08-02T19:45:30.713 に答える