行のバージョン管理に基づく分離レベルの使用

行のバージョン管理フレームワークは、SQL Server では常に有効になっており、複数の機能で使用されます。このフレームワークは、行のバージョン管理に基づく分離レベルを提供するだけでなく、トリガーと複数のアクティブな結果セット (MARS) セッションで行われた変更のサポートおよびオンラインのインデックス操作でのデータ読み取りのサポートに使用されます。

行のバージョン管理に基づく分離レベルは、データベース レベルで有効になっています。この分離レベルが有効になっているデータベースのオブジェクトにアクセスするアプリケーションでは、次の分離レベルを使用してクエリを実行できます。

  • Read Committed。次のコード例に示すように、READ_COMMITTED_SNAPSHOT データベース オプションを ON に設定して行のバージョン管理を使用します。

    ALTER DATABASE AdventureWorks2008R2
        SET READ_COMMITTED_SNAPSHOT ON;
    

    データベースで READ COMMITTED が有効になっている場合、Read Committed 分離レベルで実行されているすべてのクエリで行のバージョン管理が使用されます。つまり、読み取り操作により更新操作がブロックされることはありません。

  • 次のコード例に示すように、ALLOW_SNAPSHOT_ISOLATION データベース オプションを ON に設定することによってスナップショット分離を有効にします。

    ALTER DATABASE AdventureWorks2008R2
        SET ALLOW_SNAPSHOT_ISOLATION ON;
    

    スナップショット分離レベルで実行中のトランザクションでは、スナップショットが有効になっているデータベースのテーブルにアクセスできます。スナップショットが有効になっていないテーブルにアクセスするには、分離レベルを変更する必要があります。たとえば、次のコード例では、スナップショット トランザクションで実行中に 2 つのテーブルを結合する SELECT ステートメントを示します。1 つのテーブルは、スナップショット分離が無効なデータベースに属しています。スナップショット分離レベルで SELECT ステートメントを実行すると、実行に失敗します。

    SET TRANSACTION ISOLATION LEVEL SNAPSHOT;
    BEGIN TRAN
        SELECT t1.col5, t2.col5
            FROM Table1 as t1
            INNER JOIN SecondDB.dbo.Table2 as t2
                ON t1.col1 = t2.col2;
    

    次に、トランザクション分離レベルを Read Committed に変更するように変更した同じ SELECT ステートメントのコード例を示します。この変更により、SELECT ステートメントは正常に実行されます。

    SET TRANSACTION ISOLATION LEVEL SNAPSHOT;
    BEGIN TRAN
        SELECT t1.col5, t2.col5
            FROM Table1 as t1
            WITH (READCOMMITTED)
            INNER JOIN SecondDB.dbo.Table2 as t2
                ON t1.col1 = t2.col2;
    

アプリケーション内での分離レベルの設定方法の詳細については、「トランザクション分離レベルの調整」を参照してください。

行のバージョン管理に基づく分離レベルを使用したトランザクションの制限事項

行のバージョン管理に基づく分離レベルを使用して作業する場合は、次の制限事項を考慮してください。

  • READ_COMMITTED_SNAPSHOT は、tempdb、msdb、または master では有効にできません。

  • グローバルな一時テーブルは tempdb に格納されます。スナップショット トランザクション内でグローバルな一時テーブルにアクセスする場合は、次のいずれかの操作を行う必要があります。

    • tempdb で ALLOW_SNAPSHOT_ISOLATION データベース オプションを ON に設定します。

    • 分離ヒントを使用して、ステートメントの分離レベルを変更します。

  • スナップショット トランザクションは、次の場合に失敗します。

    • スナップショット トランザクションが開始してからデータベースにアクセスするまで、データベースが読み取り専用になっている場合。

    • 複数のデータベースのオブジェクトにアクセスするときに、スナップショット トランザクションが開始してからデータベースにアクセスするまでの間にデータベースの復旧が行われるようにデータベースの状態が変更された場合。たとえば、データベースが OFFLINE に設定されてから ONLINE に設定された場合、データベースを自動終了して開く場合、またはデータベースをデタッチ後にアタッチする場合などがあります。

  • 分散パーティション データベースのクエリなど、分散トランザクションはスナップショット分離ではサポートされていません。

  • SQL Server では、複数バージョンのシステム メタデータは保持されません。テーブルおよび他のデータベース オブジェクト (インデックス、ビュー、データ型、ストアド プロシージャ、および共通言語ランタイム関数) のデータ定義言語 (DDL) ステートメントにより、メタデータが変更されます。DDL ステートメントでオブジェクトを変更する場合、スナップショット分離では、オブジェクトへの同時参照が原因で、スナップショット トランザクションが失敗します。READ_COMMITTED_SNAPSHOT データベース オプションが ON の場合、Read Committed トランザクションにはこの制限がありません。

    たとえば、データベース管理者が、次の ALTER INDEX ステートメントを実行したとします。

    USE AdventureWorks2008R2;
    GO
    ALTER INDEX AK_Employee_LoginID
        ON HumanResources.Employee REBUILD;
    GO
    

    ALTER INDEX ステートメントの実行時にアクティブなスナップショット トランザクションでは、ALTER INDEX ステートメントの実行後に HumanResources.Employee テーブルを参照すると、エラーが発生します。行のバージョン管理を使用する Read Committed トランザクションは影響を受けません。

    注意

    BULK INSERT 操作 (たとえば、制約チェックを無効にする場合など) により、挿入先テーブルのメタデータが変更されることがあります。このような変更が発生すると、一括挿入されたテーブルにアクセスする同時実行中のスナップショット分離トランザクションは失敗します。