web-dev-qa-db-ja.com

ALLOW_SNAPSHOT_ISOLATIONおよびREAD_COMMITTED_SNAPSHOT

ほとんどのフォーラムとオンラインの例では、常に両方を推奨していますALLOW_SNAPSHOT_ISOLATIONおよびREAD_COMMITTED_SNAPSHOT誰かがスナップショット、行のバージョン管理、または同様の質問をするたびにONに設定します。

両方の設定でWord SNAPSHOTは少し混乱するでしょう。データベースエンジンがREAD_COMMITTEDのデフォルトの動作でロックの代わりに行のバージョン管理を使用するために、データベースREAD_COMMITTED_SNAPSHOTはONに設定されています無関係に何のALLOW_SNAPSHOT_ISOLATION設定。

ALLOW_SNAPSHOT_ISOLATION設定は、トランザクションの開始時にスナップショット分離を許可するためにのみオンに設定されます(例:SET TRANSACTION ISOLATION LEVEL SNAPSHOT)に関係なく of READ_COMMITTED_SNAPSHOT設定。

これら2つの設定をONに設定する唯一の理由は、READ COMMITTED行のバージョン管理[〜#〜] and [〜#〜]スナップショット分離が必要な場合です。

私の質問は、私の理解が何らかの点で間違っているのですか?そして、これら2つの設定は常に一緒にONに設定する必要があります(特に、READ COMMITTED行のバージョン管理の場合)?

40
Travis

あなたの理解は正しいです。少し混乱します。

Kim Tripp(SQL Serverのプログラマーの1人であり、SQLSkillsの不可欠な部分)は、 スナップショットアイソレーションのMCMビデオ で述べた内容を正確に実行します。ビデオで41:45まで早送りして、彼女があなたの質問に答える部分に行きます。

ALLOW_SNAPSHOT_ISOLATIONを使用する場合は、コードでSET TRANSACTION ISOLATION LEVEL SNAPSHOTを使用してください。そうしないと、メリットが得られません。

SET READ_COMMITTED_SNAPSHOT ONを設定した場合、コードを変更する必要はありません。 MS SQL Serverは、そのテーブルにスナップショット分離を自動的に適用します。

コードで別の分離レベルを要求した場合に何が起こるかを確認するためのテストは行っていません。このオプションを上書きすると思われますが、最初にテストします。

スナップショットアイソレーションを使用したパフォーマンスオーバーヘッドの概要。

スナップショット分離がアプリの予想される動作をどのように変えることができるかについての良い記事 。これは、更新ステートメントと選択ステートメントがまったく異なる予期しない結果を返す方法の例を示しています。

26
Ali Razeghi

OK、家に帰ってテストしました。これが観察です。

CREATE DATABASE TEST;
GO
CREATE TABLE TABLE1
(
    ID tinyint,
    Details varchar(10)
);
GO
INSERT INTO TABLE1
VALUES (1, 'Original');
GO

SELECT
    name,
    snapshot_isolation_state_desc,
    is_read_committed_snapshot_on
FROM sys.databases
WHERE name = 'TEST';
GO

最初のテスト両方の設定がオフであることを確認。

クエリ1

USE TEST;

BEGIN TRAN
UPDATE TABLE1
SET Details = 'Update'
WHERE ID = 1;

--COMMIT;
--ROLLBACK;
GO

クエリ2

USE TEST;

SELECT ID, Details
FROM TABLE1
WHERE ID = 1;
GO

このテストでは、クエリ2はクエリ1のコミットを待機しています。dm_tran_locksDMVは、クエリ1によって発生したTABLE1の排他ロックを示しています。

USE TEST;

SELECT
    DB_NAME(tl.resource_database_id) AS DBName,
    resource_type,
    OBJECT_NAME(resource_associated_entity_id) AS tbl_name,
    request_mode,
    request_status,
    request_session_id
FROM sys.dm_tran_locks tl
WHERE 
    resource_database_id = db_id('TEST')
    AND resource_type = 'OBJECT'

2番目のテスト、前のトランザクションをロールバックし、READ_COMMITTED_SNAPSHOTをONに設定しますが、ALLOW_SNAPSHOT_ISOLATIONをOFFのままにします。

ALTER DATABASE TEST
SET READ_COMMITTED_SNAPSHOT ON
WITH ROLLBACK IMMEDIATE;
GO

クエリ1を実行し、クエリ2を実行します。DMVはクエリ1が排他ロックを発生していることを示しますが、クエリ2はクエリ1なしで「オリジナル」の詳細を返し、トランザクションをコミットします。 READ_COMMITTED行のバージョン管理が行われているようです。

クエリ1とクエリ2にSET TRANSACTION ISOLATION LEVEL SNAPSHOT;を追加し、クエリ1またはクエリ2を実行するとエラーが返されます-このデータベースではスナップショット分離が許可されていないため、スナップショット分離トランザクションはデータベース 'TEST'にアクセスできませんでした。スナップショット分離を許可するには、ALTER DATABASEを使用します。

番目のテスト、前のトランザクションをロールバックします。 READ_COMMITTED_SNAPSHOT OFFおよびALLOW_SNAPSHOT_ISOLATION ONを設定します。

ALTER DATABASE TEST
SET READ_COMMITTED_SNAPSHOT OFF
WITH ROLLBACK IMMEDIATE;
GO

ALTER DATABASE TEST
SET ALLOW_SNAPSHOT_ISOLATION ON;
GO

クエリ1を実行してからクエリ2を実行します。DMVは、クエリ1によって発生した排他ロックを示します。クエリ2は、クエリ1の完了を待機しているようです。 ALLOW_SNAPSHOT_ISOLATIONをONにしても、READ COMMITTED行のバージョン管理が有効になっていないようです。

クエリ1とクエリ2の両方にSET TRANSACTION ISOLATION LEVEL SNAPSHOT;を追加します。クエリ1を実行してからクエリ2を実行します。DMVはクエリ1に排他ロックが発生していることを示しますが、クエリ2は「オリジナル」で詳細を返します。スナップショットの分離が行われているようです。

テストの結果から、READ_COMMITTED_SNAPSHOT自体がALLOW_SNAPSHOT_ISOLATIONの設定に関係なく、READ COMMITTED行のバージョン管理を有効/無効にすることが示されています。逆も同様です。

15
Travis

あなたの理解は正しいです。 here の短くてクリーンでシンプルな定義が好きです。

READ_COMMITTED_SNAPSHOTデータベースオプションがONの場合、コミットされた読み取り分離レベルを設定するトランザクションは、行のバージョン管理を使用します。

ALLOW_SNAPSHOT_ISOLATIONデータベースオプションがONの場合、トランザクションはスナップショット分離レベルを設定できます。

多くの誤解がMS自体に由来するようです。たとえば、 here 彼らは言う:

READ_COMMITTED_SNAPSHOTデータベースオプションをONに設定すると、データベースエンジンは、データを保護するためにロックを使用する代わりに、行のバージョン管理とスナップショット分離をデフォルトとして使用します。

ただし、前述の「スナップショット分離」は、set transaction isolation level snapshotが適用されるトランザクションの動作とは異なります。

違いはナイス説明は ここ です。

おそらく、READ_COMMITTED_SNAPSHOTがREAD_COMMITTED_ROW_VERSIONINGまたはそのようなものと名付けられた方が良いでしょう。 :)

4
o.v

私はこの要約が好き Microsoftから

READ_COMMITTED_SNAPSHOT ONオプションを設定すると、デフォルトのREAD COMMITTED分離レベルでバージョン対応の行にアクセスできます。 READ_COMMITTED_SNAPSHOTオプションがOFFに設定されている場合、バージョン対応の行にアクセスするには、各セッションのスナップショット分離レベルを明示的に設定する必要があります。

0
flam3