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 IsolationMCM 비디오에서 언급 한 내용을 그대로 따릅니다 . 비디오에서 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.