행 버전 관리 기반 격리 수준 선택
행 버전 관리 기반 격리 수준은 읽기 작업에 대한 잠금을 제거하여 동시에 더 많은 사용자가 읽을 수 있도록 합니다. MicrosoftSQL Server에는 행 버전 관리를 사용하는 두 가지 트랜잭션 격리 수준이 새로 추가되었습니다.
READ_COMMITTED_SNAPSHOT 데이터베이스 옵션을 ON으로 설정한 경우 행 버전 관리를 사용하는 새롭게 구현된 커밋된 읽기 격리
ALLOW_SNAPSHOT_ISOLATION 데이터베이스 옵션을 ON으로 설정한 경우 활성화되는 새로운 격리 수준인 스냅숏
대부분의 응용 프로그램에서는 다음과 같은 이유로 스냅숏 격리보다는 행 버전 관리를 사용하는 커밋된 읽기 격리를 사용하는 것이 좋습니다.
커밋된 읽기 격리는 스냅숏 격리보다 적은 tempdb 공간을 사용합니다.
커밋된 읽기 격리는 분산 트랜잭션에 사용할 수 있지만 스냅숏 격리는 사용할 수 없습니다.
커밋된 읽기 격리는 변경할 필요 없이 대부분의 기존 응용 프로그램에 사용할 수 있습니다. 기본 격리 수준인 커밋된 읽기를 사용하여 작성된 응용 프로그램을 동적으로 튜닝할 수 있습니다. 행 버전 관리를 사용하는지 여부에 상관없이 커밋된 읽기의 동작은 데이터베이스 옵션 설정에 따라 결정되며 응용 프로그램에 영향을 주지 않고 변경할 수 있습니다.
[!참고]
커밋된 읽기 격리의 차단 동작을 따르도록 디자인된 응용 프로그램의 경우 개발자는 커밋된 읽기 격리의 두 모드에 모두 적합하도록 응용 프로그램을 변경할 수 있습니다. 그렇지 않을 경우 READ_COMMITTED_SNAPSHOT 데이터베이스 옵션이 OFF로 유지됩니다.
스냅숏 격리는 행 버전 관리를 사용하는 커밋된 읽기 격리에는 나타나지 않는 업데이트 충돌이 발생하기 쉽습니다. 스냅숏 격리에서 실행되는 트랜잭션이 데이터를 읽고 이 데이터를 다른 트랜잭션에서 수정할 경우 스냅숏 트랜잭션에서 이 데이터를 업데이트하면 업데이트 충돌이 발생하고 트랜잭션이 종료 및 롤백됩니다. 이 문제는 행 버전 관리를 사용하는 커밋된 읽기 격리에서는 발생하지 않습니다.
행 버전 관리를 사용하는 커밋된 읽기 격리를 사용해야 할 경우
행 버전 관리를 사용하는 커밋된 읽기 격리는 문 수준의 읽기 일관성을 제공합니다. 트랜잭션 내의 각 문이 실행될 때 새 데이터 스냅숏이 생성되며 문에서 실행을 완료할 때까지 각 문에 대해 일관성 있게 유지됩니다. 다음과 같은 경우 행 버전 관리를 사용하는 커밋된 읽기 격리를 사용합니다.
행 버전 관리를 만들고 관리할 때의 증가된 오버헤드보다 동시성을 통해 얻는 이점이 더 클 때까지 읽기/쓰기가 차단되는 경우
응용 프로그램에서 실행 시간이 긴 집계나 데이터 값이 쿼리 시작 시와 동일하게 유지되어야 하는 쿼리에 대해 절대적으로 정확성이 요구되는 경우
스냅숏 격리를 사용해야 할 경우
스냅숏 격리는 트랜잭션 수준의 읽기 일관성을 제공합니다. 스냅숏 트랜잭션이 시작되면 데이터 스냅숏이 생성되며 트랜잭션 기간 동안 일관성 있게 유지됩니다. 다음과 같은 경우 스냅숏 격리를 사용합니다.
최적 동시성 제어가 필요한 경우
업데이트 충돌로 인해 트랜잭션이 롤백되어야 할 가능성이 낮은 경우
응용 프로그램에서 지정 시간 동안 일관성을 유지해야 하는 실행 시간이 긴 다중 문 쿼리를 기반으로 보고서를 생성해야 하는 경우. 스냅숏 격리의 이점은 공유 잠금을 사용하지 않고 읽기를 반복할 수 있다는 점입니다. 동시성 효과를 참조하십시오. 데이터베이스 스냅숏은 이와 비슷한 기능을 제공할 수 있지만 수동으로 구현해야 합니다. 스냅숏 격리는 데이터베이스에서 각 스냅숏 격리 트랜잭션에 대한 최신 정보를 자동으로 제공합니다.
행 버전 관리 기반 격리 수준의 이점
행 버전 관리를 사용하는 격리 수준은 다음과 같은 이점을 제공합니다.
읽기 작업에서 일관성 있는 데이터베이스 스냅숏을 검색합니다.
SELECT 문이 읽기 작업 동안 데이터를 잠그지 않습니다. 판독기도 기록기를 차단하지 않고 기록기도 판독기를 차단하지 않습니다.
다른 트랜잭션이 차단되지 않고 행을 업데이트하는 동안 SELECT 문이 마지막으로 커밋된 행 값에 액세스할 수 있습니다.
교착 상태 수가 감소됩니다.
트랜잭션에 필요한 잠금 수가 줄기 때문에 잠금을 관리하는 데 필요한 시스템 오버헤드가 줄어듭니다.
잠금 에스컬레이션이 적게 발생합니다.
행 버전 관리 기반 격리 수준의 비용
행 버전 관리 기반 격리를 사용하려면 행 버전을 관리하고 읽는 데 필요한 리소스 사용의 증가와 잠금을 최소화할 때 얻을 수 있는 동시성의 이점을 비교해야 합니다. 스냅숏 및 커밋된 읽기 격리 수준에 행 버전 관리를 사용할 때 수반되는 다음 비용을 고려하십시오.
쿼리에 필요한 버전이 오래되어 긴 버전 체인을 검색해야 할 경우 읽기 성능이 저하될 수 있습니다.
행 버전은 tempdb에서 유지 관리되기 때문에 행 버전 관리를 사용하면 데이터를 수정하는 동안 리소스 사용이 증가합니다.
READ_COMMITTED_SNAPSHOT 또는 ALLOW_SNAPSHOT_ISOLATION 데이터베이스 옵션을 ON으로 설정한 경우 행 버전 관리 기반 격리 수준을 사용하는 트랜잭션이 없더라도 특정 데이터베이스에 대한 업데이트 및 삭제 트랜잭션이 행 버전을 유지 관리해야 합니다. 행 버전을 사용하여 일관성 있는 데이터 스냅숏을 구성하려면 CPU와 메모리와 같은 시스템 리소스가 필요하며 I/O 동작이 생성될 수도 있습니다. 레코드 버전이 tempdb에 저장되기 때문에 행 버전 관리를 위해 더 많은 tempdb 페이지를 메모리에 저장할 수 있을 경우 성능이 향상되고 실행한 I/O 수가 줄어듭니다.
[!참고]
행을 삽입하면 일반적으로 행 버전이 생성되지 않습니다. 그러나 특정 조건에서 INSERT 명령이 행 버전을 생성합니다. 예를 들어 이전에 삭제한 행 버전(삭제할 레코드)이 아직 잘리지 않은 경우 고유 인덱스가 있는 테이블에 행을 삽입하면 INSERT 명령이 행 버전을 생성합니다.
tempdb에 버전을 저장할 충분한 디스크 공간이 있어야 합니다. 실행 시간이 매우 긴 트랜잭션이 있을 경우 이 시간 동안 업데이트 트랜잭션에 의해 생성되는 모든 버전이 tempdb에 저장되어야 합니다. tempdb에 공간이 부족할 경우 업데이트 작업이 실패하지 않지만 행 버전 관리를 사용하는 읽기 작업이 실패할 수 있습니다.
행 버전 관리 정보를 위해 데이터베이스 행에 14바이트가 추가되어야 합니다.
행 버전 관리 작업으로 인해 업데이트 성능이 저하될 수 있습니다. 일반 OLTP 작업에서 각 업데이트는 데이터베이스의 행 몇 개만 변경합니다. 이러한 시스템에서는 두 옵션을 ON으로 설정한 경우 데이터베이스의 업데이트 성능이 이러한 옵션을 OFF로 설정한 경우보다 몇 퍼센트만 떨어질 수 있습니다. 버전 관리되는 업데이트의 성능은 업데이트 작업 동안 보다 많은 양의 데이터를 변경할 때 더 크게 저하될 수 있습니다.
데이터 판독기에서 버전 링크 목록을 순회하는 추가 비용이 발생합니다. 스냅숏이 오래될수록 스냅숏 격리 트랜잭션에서 이 스냅숏에 액세스하는 프로세스가 더 느려집니다.
업데이트 작업에 필수적인 충돌 감지로 인해 스냅숏 격리를 사용하는 일부 업데이트 트랜잭션을 롤백해야 할 수 있습니다. 행 버전 관리를 사용하는 커밋된 읽기 격리에서 실행되는 트랜잭션에서는 업데이트 충돌이 발생하지 않습니다.
행 버전 관리를 사용하는 트랜잭션에는 다른 제한 사항이 있습니다. 자세한 내용은 행 버전 관리 기반 격리 수준 사용을 참조하십시오.
행 버전 관리 기반 격리 수준에서 이점을 얻는 시스템
행 버전 관리 기반 격리 수준에서 이점을 얻을 수 있는 시나리오는 다음과 같습니다.
읽기 전용 보고서 및 임시 쿼리가 데이터를 업데이트하는 응용 프로그램과 병렬로 실행되는 시스템
비슷한 격리 수준을 지원하는 다른 관계형 데이터베이스 시스템에서 MicrosoftSQL Server 데이터베이스 엔진으로 응용 프로그램 마이그레이션
AVG, COUNT, SUM 등 일관성 있는 집계를 얻거나 인덱스 교차 및 인덱스 조인을 수행하기 위해 반복 읽기 또는 직렬화 가능 등의 엄격한 격리 수준이 필요한 시스템
읽기/쓰기 경합으로 인해 교착 상태가 많이 일어나는 시스템