ONE QUESTION AT A TIME.

천천히 생각하고, 분명하게.

TODAY’S QUESTION1362 / 1500
데이터베이스난이도 중하5분 답변 목표 · 보강본

SQL Server 트랜잭션에서 같은 행을 두 번 읽는 사이 다른 요청이 값을 바꿨습니다. RCSI와 SNAPSHOT은 두 번째 읽기와 이후 쓰기 충돌을 어떻게 다르게 처리하나요?

잠깐, 답변을 보기 전에
먼저 내 말로 설명해 볼까요?

답변과 점검 포인트 펼치기답변 접기
01

구두 답변

정의를 외우기보다, 원리와 조건을 연결해 설명해 보세요.

RCSI(Read Committed Snapshot Isolation)는 데이터베이스 옵션을 켠 뒤 READ COMMITTED 읽기를 잠금 대신 행 버전으로 처리하는 방식입니다. 일반적으로 각 문장이 시작될 때의 커밋된 버전을 읽으므로, 같은 트랜잭션에서 두 SELECT를 실행하는 사이 커밋이 보일 수 있습니다. SNAPSHOT 격리는 트랜잭션이 시작한 스냅샷을 기준으로 읽기 때문에 한 트랜잭션 안의 반복 읽기 기준이 더 오래 유지됩니다.

따라서 단순 조회에서 읽기와 쓰기의 블로킹을 줄이고 문장 단위로 일관된 결과를 얻는 목적이면 RCSI가 적합할 수 있습니다. 여러 조회를 조합한 보고서가 모두 같은 기준 시점이어야 한다면 SNAPSHOT 또는 더 강한 설계가 필요합니다. 이름만 보고 판단하지 않고 트랜잭션 시작 시점과 첫 접근, 실제 SQL Server 옵션을 확인하겠습니다.

두 방식 모두 버전 저장 공간과 오래 열린 트랜잭션의 정리 지연을 만듭니다. SNAPSHOT에서 읽은 행을 다른 트랜잭션이 먼저 수정하면 갱신을 수행하는 시점이나 처리 과정에서 업데이트 충돌이 감지되어 트랜잭션이 실패할 수 있으므로, 애플리케이션 재시도가 필요합니다. 반면 여러 행의 불변식이나 쓰기 편향을 스냅샷이 자동으로 직렬화해 주는 것은 아니므로, 조건부 갱신·공통 잠금 행·SERIALIZABLE 등 별도 보호가 필요합니다.

두 세션에서 첫 SELECT, 중간 UPDATE, 두 번째 SELECT, UPDATE 커밋 순서를 맞춰 RCSI와 SNAPSHOT의 결과를 비교하겠습니다. 버전 저장소 사용량, 충돌·재시도율, 오래 열린 트랜잭션도 함께 관찰해야 합니다.

같은 트랜잭션이라고 같은 화면을 보는 것은 아닙니다

예를 들어 첫 SELECT에서 잔액 100을 읽은 뒤 다른 세션이 80으로 바꾸고 커밋했다고 하겠습니다. RCSI를 사용하는 일반 READ COMMITTED 읽기는 다음 SELECT가 새 문장이므로 80을 볼 수 있습니다. 한 트랜잭션 안에서 같은 행을 다시 읽었는데 값이 달라지는 것을 반복 불가능 읽기(non-repeatable read)라고 부릅니다. RCSI가 잘못 동작한 것이 아니라 문장 단위 일관성을 제공하는 계약에 맞는 결과입니다. 반면 SNAPSHOT은 해당 트랜잭션의 일관된 버전을 유지하므로 두 번째 읽기에서도 100을 보도록 합니다. 실제 스냅샷 기준은 BEGIN 문장의 벽시계 시각만으로 단정하지 않고 첫 데이터 접근과 트랜잭션 시퀀스가 설정되는 시점을 확인해야 합니다.

쓰기 전의 행 버전을 남겨 독자가 자신에게 맞는 값을 선택하게 하는 방식은 다중 버전 동시성 제어(MVCC)입니다. SQL Server에서는 RCSI를 켜는 데이터베이스 옵션과 SNAPSHOT 격리를 허용하는 옵션이 별개입니다. SNAPSHOT은 세션에서 실제 격리 수준도 선택해야 합니다. 운영 코드는 연결 풀을 통해 세션을 재사용하므로 격리 설정이 원하는 값인지 확인하겠습니다. 옵션 이름만 켰다는 이유로 모든 쿼리가 같은 스냅샷 계약을 따르는 것은 아니며, 잠금 힌트가 있는 문장도 따로 봐야 합니다.

읽기 버전과 쓰기 충돌은 별도로 처리합니다

SNAPSHOT 트랜잭션이 과거 잔액 100을 읽었다고 하겠습니다. 그 이후 다른 트랜잭션이 같은 행을 바꾸고 커밋했는데 과거 상태를 읽은 트랜잭션이 그 행을 갱신하면 업데이트 충돌로 중단될 수 있습니다. 이를 낙관적 충돌 검출이라고 설명할 수 있습니다. 반면 RCSI를 쓴다고 쓰기끼리의 잠금이 없어지는 것은 아닙니다. 실제 갱신은 여전히 다른 쓰기와 조정되므로 읽기 블로킹이 줄었다는 사실을 쓰기 병렬성이 무제한이라는 뜻으로 해석하면 안 됩니다.

충돌한 트랜잭션은 이전 읽기에 근거한 계산부터 다시 검토해야 합니다. 실패한 UPDATE 한 줄만 예전 값으로 반복하면 판단이 낡은 상태로 남습니다. 재시도 가능한 오류를 분류하고 전체 시간과 횟수를 제한하며, 그 트랜잭션 안에서 외부 결제나 이메일을 반복 실행하지 않도록 분리하겠습니다. SNAPSHOT도 서로 다른 행을 고치는 쓰기 편향까지 막지는 않으므로, 여러 행에 걸친 규칙은 SERIALIZABLE이나 공통 잠금·제약으로 보호할 필요가 있습니다.

줄어든 대기 대신 생기는 비용을 측정합니다

오래된 스냅샷을 읽는 트랜잭션이 남아 있으면 필요한 과거 버전을 바로 지울 수 없습니다. 이 보존 비용을 버전 저장소(version store)의 사용량과 정리 지연으로 관찰하겠습니다. 전통적인 버전 저장소는 tempdb에 있지만 ADR 사용 여부와 SQL Server 버전에 따라 사용자 DB의 persistent version store가 관여할 수 있으므로 실제 환경을 확인해야 합니다. 읽기를 빠르게 만들려고 연 보고서가 쓰기 부하 중 디스크 사용량을 크게 늘릴 수도 있습니다.

두 세션으로 첫 읽기, 다른 세션의 커밋, 두 번째 읽기, 첫 세션의 쓰기 순서를 통제해 보겠습니다. 예상값뿐 아니라 업데이트 충돌, 잠금 대기, 장기 트랜잭션과 버전 저장소 증가를 함께 기록합니다. 선택 기준은 무조건 더 강한 격리가 아니라, 한 문장의 일관성이 필요한지 여러 문장의 공통 기준점이 필요한지, 충돌과 버전 보존 비용을 어디까지 감당할 수 있는지입니다.

02

득점 포인트

이해가 드러나는 지점을 확인해 보세요.

  • 문장 단위 RCSI와 트랜잭션 단위 SNAPSHOT을 구분한다.
  • 블로킹 감소와 반복 보고서 일관성의 요구를 나눈다.
  • 버전 비용·업데이트 충돌·쓰기 편향을 함께 다룬다.
03

감점 포인트

놓치기 쉬운 조건과 오해를 짚어 보세요.

  • RCSI면 트랜잭션 전체가 항상 같은 시점이라고 말한다.
  • SNAPSHOT이 모든 직렬화 이상을 막는다고 말한다.
  • 버전 읽기가 아무 비용 없이 블로킹을 없앤다고 말한다.
04

더 파고들 거리

하나 더 질문하며 이해의 범위를 넓혀 보세요.

득점·감점 포인트는 학습용 자기 점검 기준이며, 특정 회사의 실제 채점표가 아닙니다.

원리부터 공부하고 싶다면

답변을 보충하는 개념·예제·슈도코드를 읽어 보세요.

← 전체 질문 보기