2.1 コミットされていない読み取り

「トランザクション分離レベル」とは、トランザクションの並列実行中に発生する上記の種類のデータの不整合のすべてまたは一部から DBMS の内部メカニズムによって提供される (つまり、特別なプログラミングを必要としない) 保護の程度を指します。SQL-92 標準では、次の 4 つの分離レベルのスケールが定義されています。

  • コミットされていない読み取り
  • 読み取りがコミットされました
  • 反復可能な読み取り
  • シリアル化可能

最初のものが最も弱く、最後のものが最も強く、後続のそれぞれには前のものがすべて含まれます。

最も低い (最初の) 分離レベル。複数の並列トランザクションが同じテーブル行を変更しようとすると、最後の行には、正常に完了したトランザクションのセット全体によって決定される値が設定されます。この場合、論理的に矛盾したデータだけでなく、変更が記録されていないデータも読み出すことが可能となる。

この分離レベルを実装する一般的な方法は、変更コマンドの実行中にデータをロックすることです。これにより、並行して実行される同じ行の変更コマンドが実際には順次実行され、変更が失われないことが保証されます。この分離レベルでは、読み取り専用トランザクションがブロックされることはありません。

2.2 コミットされた読み取り

ほとんどの産業用 DBMS、特に Microsoft SQL Server、PostgreSQL、Oracle はデフォルトでこのレベルを使用します。このレベルでは、ドラフトの「ダーティ」読み取りに対する保護が提供されますが、1 つのトランザクションの操作中に別のトランザクションが正常に完了し、それによって加えられた変更が修正されることがあります。その結果、最初のトランザクションは異なるデータセットで動作します。

完全な読み取りの実装は、ブロックまたはバージョン管理という 2 つのアプローチのいずれかに基づいて行うことができます。

読み取り可能および変更可能なデータをブロックします。

これは、書き込みトランザクションが完了するまで読み取りコミット レベル以上で動作する読み取りトランザクションの可変データをブロックすることで「ダーティ」読み取りを防止し、読み取りトランザクションによってロックされたデータは操作の完了後すぐに解放されるという点で構成されています。SELECT(したがって、特定の分離レベルでは「反復不可能な読み取り」状況が発生する可能性があります)。

並行して変更される行の複数のバージョンを保存します。

行が変更されるたびに、DBMS はこの行の新しいバージョンを作成し、データを変更したトランザクションは引き続き動作しますが、他の「読み取り」トランザクションは最後にコミットされたバージョンを返します。このアプローチの利点は、ブロッキングが防止されるため高速であることです。ただし、最初の方法と比較して、行バージョンの保存に費やされる RAM の消費量が大幅に増加します。

さらに、複数のトランザクションが並行してデータを変更すると、複数の同時トランザクションが同じデータに一貫性のない変更を加える状況が生じる可能性があります (ロックがないため、これが起こることを妨げるものは何もありません)。その後、最初にコミットしたトランザクションはその変更をメイン データベースに保存し、残りの並列トランザクションはコミットできなくなります (最初のトランザクションの更新が失われるため)。このような状況で DBMS ができることは、残りのトランザクションをロールバックして、「レコードはすでに変更されています」というエラー メッセージを発行することだけです。

特定の実装方法は DBMS 開発者によって選択され、場合によってはカスタマイズできます。したがって、MS SQL はデフォルトでロックを使用しますが、(バージョン 2005 以降では)READ_COMMITTED_SNAPSHOTデータベース パラメータを設定すると、バージョン管理戦略に切り替わり、Oracle は最初はバージョン管理スキームに従ってのみ動作します。USELASTCOMMITTEDInformix では、読み取りトランザクションが最新のコミットされたデータを受け取るようにする構成オプション (バージョン 11.1 以降) を設定することで、読み取りトランザクションと書き込みトランザクション間の競合を防ぐことができます。

2.3 反復可能な読み取り

読み取りトランザクションが、以前に読み取ったデータの変更を「認識しない」レベル。同時に、現在のトランザクションが終了するまで、他のトランザクションは現在のトランザクションによって読み取られたデータを変更できません。

共有モードのロックは、トランザクション内の任意の命令によって読み取られたすべてのデータに適用され、トランザクションが完了するまで保持されます。これにより、保留中のトランザクションによって読み取られた行が他のトランザクションによって変更されるのを防ぎます。ただし、他のトランザクションでは、現在のトランザクションに含まれる命令の検索条件に一致する改行が挿入される場合があります。現在のトランザクションによってステートメントが再開されると、新しい行がフェッチされ、ファントム読み取りが発生します。

共有ロックが各ステートメントの終了時に解放されるのではなく、トランザクションの終了まで保持されるとすると、同時実行性の度合いは分離レベルよりも低くなりますREAD COMMITTED。したがって、これ以上のトランザクション レベルを不必要に使用することは一般に推奨されません。

2.4 シリアル化可能

最高レベルの分離。トランザクションは互いに完全に分離されており、それぞれのトランザクションは並列トランザクションがないかのように実行されます。同時トランザクションが「ファントム読み取り」効果の影響を受けないのは、このレベルのみです。

2.5 実際の DBMS でのトランザクション分離のサポート

トランザクション DBMS は常に 4 つのレベルすべてをサポートしているわけではなく、追加のレベルが導入される場合もあります。断熱材の提供にもさまざまなニュアンスがあります。

そのため、原則として、Oracle はトランザクションの実装で「ダーティ読み取り」を除外するため、ゼロ レベルをサポートしません。また、形式的には、Repeatable Read レベルの設定を許可していません。つまり、(デフォルトで) と のみをサポートしRead committedますSerializable。同時に、個々のコマンドのレベルで、読み取りの再現性が実際に保証されます (SELECT最初のトランザクションのコマンドがデータベースから一連の行を選択し、この時点で並列の 2 番目のトランザクションがこれらの行の一部を変更する場合、最初のトランザクションによって受信された結果セットには、2 番目のトランザクションが存在しないかのように、変更されていない行が含まれます)。READ-ONLYOracle は、 に対応するいわゆるトランザクションもサポートしていますSerializableが、データ自体を変更することはできません。

また、Microsoft SQL Server は、4 つの標準トランザクション分離レベルすべてに加えて、トランザクションが起動前にコミットされたデータ状態と、それ自体によって行われた変更を確認する、つまりトランザクションが次のように動作する SNAPSHOT レベルをサポートしています。起動時に DB データのスナップショットを受信した場合は、それを使用して動作します。Serialized との違いは、ロックが使用されないことですが、その結果、同時トランザクションが以前に同じデータを変更していた場合、変更をコミットできない可能性があります。この場合、2 番目のトランザクションを実行しようとすると、COMMITエラー メッセージが表示され、キャンセルされます。