トランザクション分離レベル(ODBC)

トランザクション分離レベル は、トランザクション分離がどの程度成功したかを示す尺度です。 特に、トランザクション分離レベルは、以下の現象の有無によって定義されます。

  • ダーティ リードダーティ リード は、トランザクションがまだコミットされていないデータを読み取ったときに発生します。 たとえば、トランザクション 1 で行が更新されたとします。 トランザクション 2 では、トランザクション 1 が更新をコミットする前に更新された行を読み取ります。 トランザクション 1 が変更をロールバックすると、トランザクション 2 では、存在しなかったと見なされるデータを読み取ったことになります。

  • 反復不能読み取り反復不能読み取り は、トランザクションが同じ行を 2 回読み取ったが、毎回異なるデータを取得する場合に発生します。 たとえば、トランザクション 1 で行が読み取られたとします。 トランザクション 2 では、その行を更新または削除し、更新または削除をコミットします。 トランザクション 1 が行を再読み込みすると、異なる行値が取得されるか、行が削除されたことが検出されます。

  • ファントム: ファントムとは検索条件に一致しますが、最初に表示されない行のことです。 たとえば、トランザクション 1 で、ある検索条件を満たす行のセットを読み取ったとします。 トランザクション 2 では、トランザクション 1 の検索条件に一致する新しい行が (更新または挿入によって) 生成されます。 トランザクション 1 で行を読み取るステートメントが再実行されると、別の行のセットが取得されます。

これらの現象の観点から、4 つのトランザクション分離レベル (SQL-92 で定義されている) が定義されています。 次の表では、発生する可能性のある各現象を「X」でマークします。

トランザクション分離レベル ダーティ リード 反復不能読み取り ファントム
READ UNCOMMITTED x X x
READ COMMITTED -- x x
REPEATABLE READ -- -- x
シリアル化可能 -- -- --

次の表は、DBMS がトランザクション分離レベルを実装する簡単な方法を説明したものです。

重要

ほとんどの DBMS では、コンカレンシーを高めるために、これらよりも複雑なスキームが使用されます。 これらの例は、説明のためにのみ示されています。 特に、ODBC では、特定の DBMS がトランザクションをどのように相互に分離するかは規定されていません。

トランザクション分離 可能な実装
READ UNCOMMITTED トランザクションは互いに分離されません。 DBMS が他のトランザクション分離レベルをサポートしている場合、その分離レベルを実装するために使用するメカニズムは無視されます。 他のトランザクションに悪影響を及ぼさないように、通常、コミットされていない読み取りレベルで実行されているトランザクションは読み取り専用です。
READ COMMITTED トランザクションは、他のトランザクションによって書き込みロックされた行がロック解除されるまで待機します。これにより、「ダーティ」データが読み込まれるのを防ぎます。

トランザクションは、現在の行の読み取りロック (行を読み取るだけの場合) または書き込みロック (行の更新または削除の場合) を保持して、他のトランザクションによる更新または削除を防ぎます。 トランザクションは、現在の行から移動すると、読み取りロックを解除します。 コミットまたはロールバックされるまで、書き込みロックを保持します。
REPEATABLE READ トランザクションは、他のトランザクションによって書き込みロックされた行がロック解除されるまで待機します。これにより、「ダーティ」データが読み込まれるのを防ぎます。

トランザクションは、アプリケーションに返されるすべての行に対し読み取りロックを保持し、挿入、更新、または削除するすべての行に対する書き込みロックを保持します。 たとえば、トランザクションに SQL ステートメント SELECT * FROM Orders が含まれている場合、トランザクションは、アプリケーションが行をフェッチする際に、行を読み取りロックします。 トランザクションに SQL ステートメント DELETE FROM Orders WHERE Status = 'CLOSED' が含まれている場合、トランザクションは行を削除すると書き込みロックされます。

他のトランザクションはこれらの行を更新または削除できないため、現在のトランザクションは反復不能読み取りを回避します。 トランザクションは、コミットされるかロールバックされたときにのみ、ロックを解除します。
シリアル化可能 トランザクションは、他のトランザクションによって書き込みロックされた行がロック解除されるまで待機します。これにより、「ダーティ」データが読み込まれるのを防ぎます。

トランザクションは、影響を受ける行の範囲に対して読み取りロック (行の読み取りだけを行う場合) または書き込みロック (行を更新または削除できる場合) を保持します。 たとえば、トランザクションに SQL ステートメント SELECT * FROM Orders が含まれている場合、その範囲は Orders テーブル全体になります。トランザクションはテーブルを読み取りロックし、新しい行の挿入を許可しません。 トランザクションに SQL ステートメント DELETE FROM Orders WHERE Status = 'CLOSED' が含まれている場合、範囲はすべての行の状態が「CLOSED」です。トランザクションは、「CLOSED」の状態を持つ Orders テーブル内のすべての行を書き込みロックし、結果の行の状態が「CLOSED」になるように行の挿入や更新を許可しません。

他のトランザクションは範囲内に行を更新または削除できないため、現在のトランザクションは反復不能読み取りを回避します。 他のトランザクションでは範囲内に行を挿入できないため、現在のトランザクションではファントムが回避されます。 トランザクションは、コミットされるかロールバックされたときにのみ、ロックを解除します。

トランザクション分離レベルは、トランザクションが行った変更を常に確認できる、トランザクション自体の変更を確認する機能に影響しないことに注意することが重要です。 たとえば、トランザクションは 2 つの UPDATE ステートメントで構成され、1 つ目は全従業員の給与を 10% 引き上げ、2 つ目はある上限を超える従業員の給与をその金額に設定します。 これは、2 番目の UPDATE ステートメントが最初 の UPDATE ステートメントの結果を確認できるため、1 つのトランザクションとしてのみ成功します。