ALLOW_SNAPSHOT_ISOLATIONおよびREAD_COMMITTED_SNAPSHOT


38

オンラインフォーラムと例のほとんどは、常に両方持つことをお勧めALLOW_SNAPSHOT_ISOLATIONしてREAD_COMMITTED_SNAPSHOT、誰かがスナップショット、行バージョン管理または類似の質問をされるたびにONに設定します。

どちらの設定でもSNAPSHOTという言葉は少し混乱するものと思います。データベースエンジンがREAD_COMMITTEDのデフォルトの動作にロックの代わりに行バージョン管理を使用するために、データベースREAD_COMMITTED_SNAPSHOTはどの設定に関係なく ONに設定されると考えましたALLOW_SNAPSHOT_ISOLATION

ALLOW_SNAPSHOT_ISOLATION設定は、トランザクション(例えばSETトランザクション分離レベルのスナップショット)を起動するときだけスナップショット分離を可能にするために、ONに設定されているにかかわらずREAD_COMMITTED_SNAPSHOT設定。

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

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

回答:


25

あなたの理解は正しいです。少しわかりにくいです。

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は、そのテーブルにスナップショット分離を自動的に適用します。

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

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

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


リンクをありがとう。他のBOLと同様に、彼女はこれら2つの設定を独立してまとめて議論しました(それが少し混乱するか、おそらく私が考えすぎているところです)。理解を深めるためにテストする必要がありました。
トラビス

4
これはすばらしい答えであり、いくつかの項目のみを明確にしたいと思います。まず、ビデオをスキャンするだけの場合は、23:18と41:45から開始します。早い時期に詳細が追加されます。Kimは元の質問への回答に言及していますが、両方を使用する場合はコードを変更する必要があります。Read_Committed_Snapshotはステートメントレベルの分離です。つまり、現在実行中のステートメントにのみ適用されます。Allow_Snapshot_Isolationは、トランザクションレベルの分離であり、Begin TranとCommitの間のすべてです。これらは別々に使用できますが、行ごとに同じ14バイトのオーバーヘッドが確立されます。
デラックス

確立中の14バイトのオーバーヘッドに関する詳細を追加していただきありがとうございます。キムはビデオでそれを調べますが、テキストでそれをここに持つことは非常に便利です。
アリラゼギ

15

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をオンに設定しますが、ALLOW_SNAPSHOT_ISOLATIONはオフのままにします。

ALTER DATABASE TEST
SET READ_COMMITTED_SNAPSHOT ON
WITH ROLLBACK IMMEDIATE;
GO

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

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

3番目のテスト、前のトランザクションをロールバックします。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をオンにしても、READ COMMITTED行のバージョン管理は有効になりません。

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

テストからの観察は、READ_COMMITTED_SNAPSHOTそれ自体がALLOW_SNAPSHOT_ISOLATION設定に関係なくREAD COMMITTED行のバージョン管理を有効化/無効化すること、およびその逆を示しています。


4

あなたの理解は正しいです。私はここから短く、きれいでシンプルな定義が好きです

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

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

MS自体から多くの誤解が生じているようです。たとえば、ここで彼らは言います:

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

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

違いについては、こちらに説明があります

おそらく、READ_COMMITTED_SNAPSHOTの名前がREAD_COMMITTED_ROW_VERSIONINGまたはそのようなものであるとよいでしょう。:)


0

はマイクロソフトからのこの要約好きです:

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.