同時実行の影響

あるユーザーがデータを変更すると、同じデータを同時に読み取ったり変更している他のユーザーに影響します。このようなユーザーを、データに同時アクセスしているユーザーと呼びます。データ ストレージ システムで同時実行が制御されていない場合は、次のような副作用が生じることがあります。

  • 更新データの喪失

  • 非コミット依存 (ダーティ リード)

  • 不一致分析 (反復不能読み取り)

  • ファントム読み取り

  • 行の更新による読み取りの欠落および重複

更新データの喪失

この問題は、複数のトランザクションが同じ行を選択し、その行の元の値を更新すると発生します。トランザクションは互いに相手を認識しません。更新によって他のトランザクションによる更新データが上書きされれば、そのデータが失われてしまいます。

たとえば、2 人の編集者が同じ文書のコピーを作成したとします。2 人が自分のコピーを変更し、その変更内容を保存して、元の文書を上書きしたとします。変更したコピーを最後に保存した編集者により、他の編集者が行った変更が上書きされます。1 人の編集者が終了してトランザクションをコミットするまで、他の編集者がファイルにアクセスできないようにすれば、この問題を防ぐことができます。

非コミット依存 (ダーティ リード)

非コミット依存は、トランザクションによって更新されている行を別のトランザクションが選択するときに発生します。2 番目のトランザクションが読み取るデータは、まだコミットされていないので、行を更新しているトランザクションによって変更される可能性があります。

たとえば、ある編集者が電子文書を変更しているとします。その間、他の編集者はそれまでの変更が反映された文書を受け取って、読者に配布します。その後、最初の編集者がそれまでの変更を誤りと判断して取り消し、保存したとします。配布されている文書には取り消した編集内容が含まれているため、既に存在しない文書として扱う必要があります。最初の編集者が最後に変更を保存してトランザクションをコミットするまで、変更された文書をだれも読み取ることができないようにすれば、この問題を防ぐことができます。

不一致分析 (反復不能読み取り)

不一致分析は、別のトランザクションが同じ行に数回アクセスし、それぞれの場合で異なったデータを読み取るときに発生します。不一致分析は、あるトランザクションがデータを変更している間に別のトランザクションがそのデータを読み取るという点で非コミット依存と似ています。ただし不一致分析の場合、別のトランザクションが読み取るデータは変更を行ったトランザクションによってコミットされています。また、同じ行が複数回読み取られ、そのたびにトランザクションによって情報が変更されます。そのため、反復不能読み取りと呼ばれます。

たとえば、編集者が同じ文書を 2 回読んだ場合に、1 回目と 2 回目の間に執筆者が文書を変更したとします。編集者が 2 回目に文書を読んだときには、内容が大幅に変更されていました。最初に読んだ内容と同じものは再現されません。編集者が最終的に読み終わるまで執筆者が文書を変更できないようにすれば、この問題を防ぐことができます。

ファントム読み取り

ファントム読み取りは、トランザクションによって読み取られる一連の行のどれかについて挿入または削除が行われるときに発生します。別のトランザクションで削除が行われた場合、2 回目以降の読み取りでは、一連の行に対する最初の読み取りで得られた行のデータが得られなくなります。同様に、別のトランザクションで挿入が行われた場合、2 回目以降の読み取りでは、一連の行に対する最初の読み取りで得られなかった行のデータが読み取られます。

たとえば、執筆者から受け取った文書を編集者が編集するとします。制作部門が編集内容を文書のマスタ コピーに反映しているときに、新しい未編集のデータが執筆者によって追加されたとします。反復不能読み取りの状況と同様に、編集者および制作部門が元の文書の編集を終了するまでその文書に新しいデータを追加できないようにすれば、この問題を防ぐことができます。

行の更新による読み取りの欠落および重複

  • 更新された行の欠落または更新された行の複数回表示

    READ UNCOMMITTED レベルで実行されるトランザクションでは共有ロックが取得されないため、現在のトランザクションで読み取り中のデータが他のトランザクションで変更されることがあります。READ COMMITTED レベルで実行されるトランザクションでは共有ロックが取得されますが、行ロックまたはページ ロックは行が読み取られた時点で解放されます。どちらの場合も、インデックスをスキャンしているときに、読み取り中の行のインデックス キー列が他のユーザーによって変更された場合は、このキーの変更によって行がスキャン前の位置に移動すると、その行は再び出現する可能性があります。同様に、キーの変更によって、既に読み取ったインデックスの位置に行が移動すると、その行は出現しない可能性があります。この問題を回避するには、SERIALIZABLE または HOLDLOCK のヒントや、行のバージョン管理を使用します。詳細については、「テーブル ヒント (Transact-SQL)」および「データベース エンジンでの行のバージョン管理に基づく分離レベル」を参照してください。

  • 更新の対象でなかった 1 行または複数行の欠落

    READ UNCOMMITTED を使用している場合、クエリで割り当て順序スキャン (IAM ページの使用) によって行を読み取っているときに、他のトランザクションによってページ分割が発生すると、行が欠落する可能性があります。READ COMMITTED を使用している場合は、ページ分割時にテーブル ロックが保持されているため、この問題は発生しません。また、クラスタ化インデックスを含まないテーブルの場合は、更新時にページ分割が行われることはないため、この問題は発生しません。