SQL Server-비 블로킹 select 문에 대한 격리 수준은 무엇입니까? 및 삽입을 수행하는 장기 실행

SQL Server 2008 R2의 테이블에서 일부 삭제, 업데이트 및 삽입을 수행하는 장기 실행 트랜잭션 (예 : T1)이 있습니다. 동시에 다른 프로세스가이 테이블에서 select 문을 정기적으로 실행합니다.

기본 격리 설정 (READ COMMITTED I think?)에서 T1은 트랜잭션이 커밋되거나 롤백 될 때까지 select 문이 실행되지 않도록 차단합니다.

내가보고 싶은 것은 트랜잭션이 진행되는 동안에도 select 문이 일관된 데이터에서 작동하는 것입니다. SNAPSHOT 격리가 도움이 될 수 있다고 생각하지만 올바른 방향으로 가고 있는지 확실하지 않습니다. 이것이이 애플리케이션에 가장 적합한 분리 수준입니까?

둘째, select 문을 호출하는 프로세스는 제어 할 수 없지만 T1을 호출하는 .NET 응용 프로그램은 제어 할 수 있습니다. select 문과 T1에서 격리 수준을 변경해야합니까, 아니면 T1 만 다른 격리 수준을 갖는 것으로 표시하는 것으로 충분합니까?



답변

이상적인 세계에서는 SNAPSHOT과 READ COMMITTED SNAPSHOT (RCSI)의 두 가지 중에서 선택할 수 있습니다. 워크로드에 적합한 것을 결정하기 전에 트랜잭션 격리 수준의 기본 사항 을 이해해야 합니다 . 특히 RCSI로 이동 한 결과 나타날 수 있는 다른 결과알고 있어야합니다 .

select 문을 생성하는 응용 프로그램을 제어 할 수 없으므로 이상적인 세계가 아닌 것처럼 들립니다. 이 경우 선택 사항이 READ COMMITTED 대신 RCSI를 자동으로 사용하도록 해당 데이터베이스에 RCSI를 사용하는 것이 유일한 옵션입니다.


답변

맞습니다. SNAPSHOT 격리를 사용하여 트랜잭션이 시작되기 전에 일관성 있고 커밋 된 데이터를 얻으십시오.

커밋되지 않은 읽기 격리 (일명 NOLOCK 힌트)는 더티, 일관되지 않은 데이터를 읽습니다.

SNAPSHOT 격리를 사용하면 앞으로 모든 SELECT에 적용됩니다. ALTER DATABASE이 경우 READ_COMMITTED_SNAPSHOT으로 실행하십시오.

편집 : ALTER DATABASE의 링크 + 인용문 추가 (내 굵은 글씨)

데이터베이스 레벨에서 읽기 커밋 된 스냅 샷 옵션을 활성화합니다. 사용하도록 설정하면 트랜잭션이 스냅 숏 격리를 사용하지 않는 경우에도 DML 문이 행 버전 생성을 시작합니다. 이 옵션이 활성화되면 읽기 커밋 격리 수준을 지정하는 트랜잭션은 잠금 대신 행 버전 관리를 사용합니다. 트랜잭션이 커밋읽기 격리 수준 에서 실행될 때 모든 명령문은 명령문 시작시 존재하는 데이터의 스냅 샷을 봅니다.

그리고 Snapshot Isolation 사용 (굵은 글씨)

READ_COMMITTED_SNAPSHOT 데이터베이스 옵션 은 데이터베이스에서 스냅 샷 격리가 활성화 된 경우 기본 READ COMMITTED 격리 수준 의 동작을 결정 합니다. READ_COMMITTED_SNAPSHOT ON을 명시 적으로 지정하지 않으면 READ COMMITTED가 모든 암시 적 트랜잭션에 적용됩니다. 이는 READ_COMMITTED_SNAPSHOT OFF (기본값) 설정과 동일한 동작을 생성합니다. READ_COMMITTED_SNAPSHOT OFF가 적용되면 데이터베이스 엔진은 공유 잠금을 사용하여 기본 격리 수준을 적용합니다. READ_COMMITTED_SNAPSHOT 데이터베이스 옵션을 ON으로 설정하면 데이터베이스 엔진은 잠금을 사용하여 데이터를 보호하는 대신 행 버전 관리 및 스냅 샷 격리를 기본값으로 사용합니다.

예.

RCSI를 활성화하면 읽기가 일관된 데이터를 얻을 수 있으며 작성자가 차단하지 않고 읽기 커밋을 계속 사용할 수 있습니다.


답변

다음 질문과 답변을 읽어보십시오. 데이터베이스 잠금 문제? .

db 수준에서 사용할 올바른 격리 수준을 찾는 것이 데이터베이스를 건드리고 코드를 변경하는 모든 응용 프로그램을 변경하기가 어렵 기 때문에 지금이 문제를 해결하는 데 도움이되는 가장 빠른 방법입니다. “select 문을 호출하는 프로세스를 제어 할 수 없습니다”라고 말 했으므로 가장 빠른 대답은 db를 Read Committed Snapshot 격리 수준으로 전환하는 것이므로 읽기 쿼리를 건드리지 않습니다. 그렇지 않으면 큰 트랜잭션 중에 데이터를 읽는 세션에 대해 스냅 샷 격리 수준을 사용해야합니다.

올바른 것을 선택하는 방법에 대한 자세한 내용은 행 버전 관리 기반 격리 수준 선택을 참조하십시오 .