sql >> データベース >  >> RDS >> Database

シリアル化可能な分離レベル

    [シリーズ全体のインデックスを参照]

    多くの本番T-SQLコードは、実行中に基になるデータが変更されないという暗黙の前提で記述されています。このシリーズの前回の記事で見たように、これは安全ではない仮定です。単一のステートメントの実行中でも、データとインデックスのエントリが私たちの下を移動する可能性があるためです。

    T-SQLプログラマーが、他のプロセスによる同時データ変更によって発生する可能性のある種類の正確性とデータ整合性の問題を認識している場合、最も一般的に提供されるソリューションは、脆弱なステートメントをトランザクションでラップすることです。同じ種類の推論が、デフォルトで自動コミットトランザクションにすでにラップされているシングルステートメントの場合にどのように適用されるかは明確ではありません。

    それはさておき、トランザクションでT-SQLコードの重要な領域を保護するという考えは、ACIDトランザクションプロパティによって提供される保護の誤解に基づいているようです。現在の議論の頭字語の重要な要素は、分離です。 財産。トランザクションを使用すると、他の同時アクティビティの影響から自動的に完全に分離されるという考え方です。

    問題の真実は、SERIALIZABLEより下のトランザクションです のみを提供する 現在有効なトランザクション分離レベルに依存する分離の。これが私たちの日常のTにとって何を意味するのかを理解する SQLコーディングの実践では、最初にシリアル化可能な分離レベルについて詳しく見ていきます。

    シリアル化可能な分離

    シリアル化可能は、標準のトランザクション分離レベルの中で最も分離されています。 デフォルトでもあります SQL Server(ほとんどの商用データベースシステムと同様)はこの点で標準とは異なりますが、SQL標準で指定されている分離レベル。 SQL Serverのデフォルトの分離レベルは読み取りコミットされています。これは、このシリーズの後半で説明する、より低い分離レベルです。

    SQL-92標準のシリアル化可能な分離レベルの定義には、次のテキストが含まれています(私の強調):

    シリアル化可能な実行は、一部のシリアル実行と同じ効果を生成するSQLトランザクションを同時に実行する操作の実行として定義されます。 それらの同じSQLトランザクションの。シリアル実行とは、次のSQLトランザクションが開始する前に、各SQLトランザクションが完了するまで実行される実行です。

    ここでは、真にシリアル化されたの間に重要な違いがあります。 実行(各トランザクションが実際には次のトランザクションが開始する前に完全に排他的に実行される)およびシリアル化可能 分離。トランザクションはあたかも同じ効果を持つ必要があるだけです。 それらは連続して(不特定の順序で)実行されました。

    言い換えると、実際のデータベースシステムは物理的にオーバーラップすることができます。 シリアル化可能なトランザクションの実行は、それらのトランザクションの効果がシリアル実行の可能な順序に対応している限り、時間内に実行されます(これにより同時実行性が向上します)。つまり、シリアル化可能なトランザクションは潜在的にシリアル化可能 実際にシリアル化されるのではなく

    論理的にシリアル化可能なトランザクション

    すべての物理的な考慮事項(ロックなど)をしばらく脇に置いて、2つの同時シリアル化可能なトランザクションの論理処理についてのみ考えてください。

    多数の行を含むテーブルについて考えてみます。そのうちの5つは、興味深いクエリ述語を満たしています。シリアル化可能なトランザクションT1 この述部に一致するテーブル内の行数のカウントを開始します。 T 1のしばらく後 開始しますが、コミットする前に、2番目のシリアル化可能なトランザクションT 2 開始します。トランザクションT2 クエリ述語も満たす4つの新しい行をテーブルに追加し、コミットします。次の図は、イベントの時系列を示しています。

    問題は、シリアル化可能なトランザクションT 1でクエリを実行する必要がある行数です。 カウントしますか? ここでは純粋に論理的な要件について考えていることを忘れないでください。したがって、どのロックが取られる可能性があるかなどについては考えないでください。

    2つのトランザクションは時間的に物理的にオーバーラップしますが、これは問題ありません。シリアル化可能な分離では、これら2つのトランザクションの結果がいくつかの可能なシリアル実行に対応している必要があります。トランザクションT1の論理シリアルスケジュールには明らかに2つの可能性があります。 およびT2

    最初の可能なシリアルスケジュールを使用する(T 1 次にT2 )T 1 クエリをカウントすると、5行が表示されます 、最初のトランザクションが完了するまで2番目のトランザクションは開始されないためです。 2番目に可能な論理スケジュールであるT1 クエリは9行をカウントします 、カウントトランザクションが開始する前に4行の挿入が論理的に完了したためです。

    両方の答えは、シリアル化可能な分離の下で論理的に正しいです。さらに、他の答えは不可能です(したがって、トランザクションT 1 たとえば、7行を数えることができませんでした)。 2つの可能な結果のどちらが実際に観察されるかは、正確なタイミングと、使用中のデータベースエンジンに固有の実装の詳細の数によって異なります。

    トランザクションが実際に何らかの形で時間内に並べ替えられているとは結論付けていないことに注意してください。最初の図に示すように、物理的な実行は、2つの可能なシリアルシーケンスのいずれかで実行された場合に何が起こったかを結果が反映していることをデータベースエンジンが保証する限り、自由にオーバーラップできます。

    シリアル化可能および並行性の現象

    論理シリアル化に加えて、SQL標準では、シリアル化可能な分離レベルで動作するトランザクションで特定の同時実行現象が発生してはならないことも規定されています。コミットされていないデータを読み取ってはなりません(ダーティリード );また、データが読み取られると、同じ操作を繰り返すと、まったく同じデータセットが返される必要があります(繰り返し可能な読み取り ファントムなし 。

    この標準では、これらの同時実行現象は、直接的な結果としてシリアル化可能な分離レベルで除外されると述べています。 トランザクションを論理的にシリアル化できるようにする必要があります。言い換えれば、直列化可能性の要件はそれ自体で十分です ダーティリード、繰り返し不可能なリード、およびファントム同時実行現象を回避するため。対照的に、3つの並行性現象を回避するだけでは十分ではありません 後で説明するように、直列化可能性を保証します。

    直感的には、シリアル化可能なトランザクションは、完全に分離して実行されたかのように動作する必要があるため、同時実行に関連するすべての現象を回避します。その意味で、シリアル化可能なトランザクション分離レベルは、T-SQLプログラマーの一般的な期待と非常によく一致しています。

    シリアル化可能な実装

    SQL Serverは、シリアル化可能な分離レベルのロック実装を使用します。この実装では、物理ロックが取得され、保持されます トランザクションの最後まで(したがって、非推奨のテーブルヒントHOLDLOCK SERIALIZABLEの同義語として 。

    新しいデータまたは変更されたデータがトランザクションによって以前に処理された行の範囲に表示される可能性があるため、この戦略は完全な直列化可能性の技術的保証を提供するには十分ではありません。この同時実行現象はファントムと呼ばれ、どのシリアルスケジュールでも発生しなかった影響をもたらす可能性があります。

    ファントム同時実行現象からの保護を確実にするために、SQL Serverがシリアル化可能な分離レベルで取得するロックには、キー範囲ロックを組み込むこともできます。 以前に調べたインデックスキー値の間に新しい行または変更された行が表示されないようにします。レンジロックは常にではありません シリアル化可能な分離レベルで取得。一般的に言えることは、SQL Serverは、シリアル化可能な分離レベルの論理要件を満たすのに十分なロックを常に取得するということです。実際、ロックの実装では、直列化可能性を保証するために実際に必要とされるよりも多くの、より厳密なロックを取得することがよくありますが、私は逸脱します。

    ロックは、シリアル化可能な分離レベルの可能な物理的な実装の1つにすぎません。 SQLServerロック実装の特定の動作をシリアライズ可能の論理定義から精神的に分離するように注意する必要があります。

    代替の物理戦略の例として、シリアル化可能なスナップショットアイソレーションのPostgreSQL実装を参照してください。ただし、これは1つの代替手段にすぎません。もちろん、それぞれの異なる物理的な実装には、独自の長所と短所があります。余談ですが、Oracleは、シリアル化可能な分離レベルの完全準拠の実装をまだ提供していないことに注意してください。 名前付きの分離レベルがあります シリアル化可能ですが、トランザクションがいくつかの可能なシリアルスケジュールに従って実行されることを真に保証するものではありません。オラクルは代わりにスナップショットアイソレーションを提供します シリアル化が要求された場合、PostgreSQLがシリアル化可能なスナップショットアイソレーションの前に行ったのとほぼ同じ方法で( SSI )が実装されました。

    スナップショットアイソレーションは、書き込みスキューなどの同時実行性の異常を防止しません。これは、真にシリアル化可能な分離では不可能です。興味がある場合は、上記のSSIリンクで、スナップショットアイソレーションによって許可される書き込みスキューおよびその他の同時実行効果の例を見つけることができます。また、このシリーズの後半で、スナップショットアイソレーションレベルのSQLServer実装についても説明します。

    ポイントインタイムビュー?

    論理的な直列化可能性と物理的に直列化された実行の違いについて話すことに時間を費やした理由の1つは、実際には存在しない可能性のある保証を簡単に推測できることです。たとえば、シリアル化可能なトランザクションを実際にと考える場合 次々に実行すると、シリアル化可能なトランザクションは、トランザクションの開始時に存在していたデータベースを必然的に認識し、特定の時点のビューを提供すると推測できます。

    実際、これは実装固有の詳細です。前の例を思い出してください。ここでは、シリアル化可能なトランザクションT 1 合法的に5行または9行を数える可能性があります。 9のカウントが返された場合、最初のトランザクションには、トランザクションの開始時に存在していなかった行が明確に表示されます。この結果はSQLServerでは可能ですが、PostgreSQL SSIでは不可能ですが、どちらの実装もシリアル化可能な分離レベルに指定された論理動作に準拠しています。

    SQL Serverでは、シリアル化可能なトランザクションは、トランザクションの開始時に存在していたデータを必ずしも認識しません。むしろ、SQL Server実装の詳細は、データが最初にアクセスのためにロックされた時点で、シリアル化可能なトランザクションが最新のコミットされたデータを参照することを意味します。さらに、最終的に読み取られる最新のコミットされたデータのセットは、トランザクションが終了する前にメンバーシップを変更しないことが保証されています。

    次回

    このシリーズの次のパートでは、反復可能な読み取り分離レベルについて説明します。これにより、シリアル化可能よりも弱いトランザクション分離保証が提供されます。

    [シリーズ全体のインデックスを参照]


    1. ORA-00942:schema.tableから選択できますが、tableから選択できませんか?

    2. 最新のデータベースバックアップステータスを取得するための専用のストアドプロシージャ

    3. OracleへのEFクエリがORA-12704をスローします:文字セットの不一致

    4. SQL Serverで外部キーの依存関係を見つける方法は?