ALLOW_SNAPSHOT_ISOLATION 및 READ_COMMITTED_SNAPSHOT


38

온라인 포럼 및 예제의 대부분은 누군가가 스냅 샷, 행 버전 관리 또는 유사한 질문을 할 때마다 항상 둘 다 가지고 ALLOW_SNAPSHOT_ISOLATION있고 READ_COMMITTED_SNAPSHOTON으로 설정되도록 제안합니다 .

두 가지 설정에서 SNAPSHOT이라는 단어가 약간 혼란스러워집니다. 데이터베이스 엔진이 READ_COMMITTED 기본 동작에 대한 잠금 대신 행 버전 관리를 사용하기 위해 데이터베이스 는 어떤 설정에 관계없이READ_COMMITTED_SNAPSHOT ON으로 설정 되었다고 생각했습니다 .ALLOW_SNAPSHOT_ISOLATION

ALLOW_SNAPSHOT_ISOLATION설정은 트랜잭션 (예 : SET 트랜잭션 격리 수준 스냅 샷을) 시작하는 경우에만 스냅 숏 격리 할 수 있도록 ON으로 설정 에 관계없이 의 READ_COMMITTED_SNAPSHOT설정.

이 두 설정을 ON으로 설정해야하는 유일한 이유는 READ COMMITTED 행 버전 관리 및 스냅 샷 격리가 필요한 경우입니다.

내 질문은 내 이해가 어떤 식으로 잘못 되었습니까? 그리고이 두 설정은 항상 함께 ON으로 설정해야합니까 (특히 READ COMMITTED 행 버전 관리의 경우)?

답변:


25

이해가 정확합니다. 약간 혼란스러워집니다.

Kim Tripp (SQL Server의 프로그래머 중 하나이며 SQLSkills의 필수 부분)는 Snapshot Isolation 의 MCM 비디오에서 언급 한 내용을 그대로 따릅니다 . 비디오에서 41:45로 빨리 감아 그녀가 당신의 질문에 대답하는 부분에 도달하십시오.

사용 ALLOW_SNAPSHOT_ISOLATION하는 경우 SET TRANSACTION ISOLATION LEVEL SNAPSHOT코드에서 사용해야 합니다. 그렇지 않으면 이점이 없습니다.

을 설정 SET READ_COMMITTED_SNAPSHOT ON하면 코드를 수정할 필요가 없습니다. MS SQL Server는 해당 테이블에 대한 스냅 샷 격리를 자동으로 적용합니다.

코드에서 다른 격리 수준을 요청하면 어떤 일이 발생하는지 테스트하지 않았 으므로이 옵션을 덮어 쓰지만 먼저 테스트 할 것입니다.

Snapshot Isolation을 사용하여 성능 오버 헤드를 간단히 살펴보십시오.

스냅 숏 격리 앱의 예상 동작을 변경할 수있는 방법에 대한 좋은 기사 . 업데이트 문과 select 문이 완전히 다른 예상치 못한 결과를 반환하는 방법의 예를 보여줍니다.


링크 주셔서 감사합니다. 다른 BOL과 마찬가지로, 그녀는이 두 가지 설정을 독립적으로 그리고 집합 적으로 논의했습니다. 더 잘 이해하기 위해 테스트해야했습니다.
— 트래비스

4
이것은 훌륭한 답변이며 몇 가지 항목 만 명확히하고 싶습니다. 먼저 비디오를 스캔하는 경우 23:18과 41:45에서 시작하십시오. 초기에는 더 자세한 내용이 추가됩니다. Kim은 원래 질문에 대한 답변을 언급하지만 둘 다 사용하는 경우에도 코드를 수정해야합니다. Read_Committed_Snapshot은 명령문 레벨 분리입니다. 즉, 현재 실행중인 명령문에만 적용됩니다. Allow_Snapshot_Isolation은 트랜잭션 수준 격리이며, Tran Tran과 Commit 사이의 모든 것입니다. 개별적으로 참여할 수 있지만 행당 동일한 14 바이트 오버 헤드가 설정됩니다.
— Delux

설정중인 14 바이트 오버 헤드에 대한 추가 정보를 추가해 주셔서 감사합니다. Kim은 비디오에서이 작업을 수행하지만 여기에 텍스트로 포함시키는 것이 매우 유용합니다.
— 알리 Razeghi

15

좋아, 집으로 돌아와서 테스트했다. 관찰 결과는 다음과 같습니다.

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

두 설정 모두 OFF로 확인 된 첫 번째 테스트 .

쿼리 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_locks DMV는 쿼리 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'

두 번째 테스트 , 이전 트랜잭션 롤백, 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 행 버전 관리가 적용된 것 같습니다.

SET TRANSACTION ISOLATION LEVEL SNAPSHOT;쿼리 1 및 쿼리 2를 추가 하고 쿼리 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 행 버전 관리가 활성화되지 않은 것 같습니다.

SET TRANSACTION ISOLATION LEVEL SNAPSHOT;쿼리 1과 쿼리 2에 모두 추가 쿼리 1을 실행 한 다음 쿼리 2를 실행하십시오. DMV가 쿼리 1에 독점 잠금이 발생하는 것을 표시하는 동안 쿼리 2는 '원본'으로 세부 사항을 리턴합니다. 스냅 샷 격리가있는 것 같습니다.

테스트에서 관찰 한 바에 따르면 설정에 READ_COMMITTED_SNAPSHOT관계없이 READ COMMITTED 행 버전 관리를 활성화 / 비활성화 하는 것이 가능 ALLOW_SNAPSHOT_ISOLATION하며 그 반대도 마찬가지입니다.


4

이해가 정확합니다. 에서 짧은 깨끗하고 간단한 정의와 같은 I 여기 :

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

나는이 요약 을 Microsoft에서 좋아한다 .

READ_COMMITTED_SNAPSHOT ON 옵션을 설정하면 기본 READ COMMITTED 격리 수준에서 버전이 지정된 행에 액세스 할 수 있습니다. READ_COMMITTED_SNAPSHOT 옵션이 OFF로 설정된 경우 버전이 지정된 행에 액세스하려면 각 세션에 대한 Snapshot 격리 레벨을 명시 적으로 설정해야합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.