Repeatable Read

Repeatable Read(반복 읽기) 는 트랜잭션 내에서 같은 조회가 항상 동일한 결과를 반환하도록 보장해 재현성을 확보한다.
구현은 MVCC(스냅샷 기반) 또는 잠금 (범위·next-key) 방식으로 나뉘며, 두 방식은 가시성·충돌 처리·성능 특성이 다르다.
RR 은 Dirty Read 와 Non-repeatable Read 를 방지하지만 Phantom(범위 삽입/삭제) 은 엔진별로 다르게 처리된다.
따라서 금융·결산 같은 재현성이 중요한 워크로드에 유리하되, 실제 적용 전 DB 별 동작 확인, 재현 테스트, 성능·교착 검증, 필요 시 부분적 상향 (Serializable) 또는 리포트 분리가 필요하다.

핵심 개념

Repeatable Read 는 하나의 트랜잭션이 같은 쿼리를 여러 번 실행해도 결과가 바뀌지 않도록 보장하는 격리 수준이다.
데이터베이스는 변경 전 상태를 저장 (언두 로그) 하고 각 트랜잭션에 스냅샷을 제공함으로써 이를 구현한다.
다만 구현 방식에 따라 ’ 팬텀 ’ 이나 ’ 쓰기 왜곡 ’ 같은 특수한 동시성 문제가 남을 수 있으므로, 실무에선 사용 전 DB 엔진의 동작을 확인하고 트랜잭션을 짧게 유지하며 모니터링을 준비해야 한다.

핵심 개념 (한글·약어)정의 (한 문장)왜 중요한가
반복 읽기 (Repeatable Read, RR)동일 트랜잭션 내 반복 조회 결과의 일관성 보장보고·정산 등 재현성 확보 필요 경로에서 신뢰성 제공
다중버전동시성제어 (MVCC)트랜잭션별 버전을 유지해 읽기 비차단을 제공높은 읽기 동시성·성능 확보
언두 로그 (Undo Log)변경 이전 상태 보관으로 롤백·스냅샷 지원스냅샷/일관적 읽기의 근간
갭/넥스트키 락 (Gap/Next-key Lock)범위 잠금으로 삽입에 의한 팬텀 방지팬텀 차단으로 범위조회 일관성 강화 (엔진 의존)
팬텀 리드 (Phantom Read)동일 조건의 조회 결과 행수가 달라지는 현상집계/범위 조회의 일관성 문제 핵심
쓰기 왜곡 (Write Skew)MVCC 환경에서 제약 위배를 야기할 수 있는 동시 쓰기 패턴RR 에서 놓칠 수 있는 제약 위반 시나리오
트랜잭션 길이 관리트랜잭션을 짧게 유지하는 운영 규칙장기 트랜잭션으로 인한 락·버전 누적 회피
데드락/락 대기 모니터링락 충돌·교착을 감시하는 운영 지표문제 조기 탐지·가용성 확보
엔진별 특성DBMS 별 RR 구현 차이 요약동일 표기라도 동작 달라 적용 방식 결정 요인
  • 핵심 개념들은 이론 (스냅샷·락) 과 운영 (트랜잭션 길이·모니터링) 으로 나뉘며, 실무 적용 시 두 축을 함께 고려해야 안정적으로 운영할 수 있다.

개념 상호관계 및 방향성

출발 개념 → 도착 개념관계 유형 (무엇을 위해)방향성·설명
언두 로그 → MVCC기초 제공언두 로그가 버전 저장을 가능케 하여 MVCC 구현 기반을 제공
MVCC → 스냅샷제공MVCC 는 트랜잭션별 스냅샷을 만들어 RR 동작을 가능하게 함
스냅샷 → RR보장스냅샷으로 동일 트랜잭션 내 반복 조회 결과 일관성 보장
락 (갭) → 팬텀 방지물리적 차단gap/next-key lock 은 삽입으로 인한 팬텀을 차단 (락 기반 방식)
MVCC ↔ Write Skew가능성 제공MVCC 는 읽기 비차단을 제공하지만 특정 동시 쓰기 시 write skew 를 허용할 수 있음
트랜잭션 길이 → 성능/버전 bloat영향긴 트랜잭션은 버전 유지 기간을 늘려 MVCC bloat·I/O 증가 유발
인덱스 설계 → 락 범위영향적절한 인덱스는 스캔 범위를 줄여 락 범위·잠금 대기 감소
  • 방향성은 ’ 기초 → 구현 → 보장 ‘(Undo→MVCC→Snapshot→RR) 과 ’ 운영 변수 → 영향 ‘(트랜잭션 길이/인덱스 → 성능·락 범위) 으로 구분된다.
  • 실무에서는 이 흐름을 이해해 ’ 어떤 요소를 튜닝하면 어느 문제가 완화되는지 ’ 가 명확해져야 한다.

개념별 실무 적용 매핑표

개념실무에서 무엇을 (What)어떻게 적용 (How)왜 중요한가 (Why)
반복 읽기 (RR)보고·정산 트랜잭션의 일관성 확보DB 격리 수준 설정 또는 쿼리별 적용재현성 높은 결과로 비즈니스 신뢰성 유지
MVCC높은 읽기 동시성 제공MVCC 지원 엔진 사용 (설정 없음/엔진 기본)읽기 성능 개선, 동시성 확보
언두 로그스냅샷·롤백 지원DB 운영 (undo/undo retention) 모니터링스냅샷 유효성·복구 가능성 보장
갭 락범위 삽입을 제어InnoDB 등에서 범위 락 허용/튜닝팬텀 방지로 집계 일관성 유지
팬텀 리드집계/범위 조회 신뢰성 문제격리 상향 또는 락/재검증 적용집계 오류·결산 오류 예방
쓰기 왜곡제약 위반 가능성제약 검증 시 commit-time recheck 또는 상향 격리비즈니스 무결성 보장
트랜잭션 길이운영 성능 영향트랜잭션 분할, 외부 호출 분리락 유지·버전 bloat 최소화
데드락 모니터가용성 보호Deadlock 탐지·알림·자동 리커버리서비스 중단 방지
엔진별 특성적용 정책 결정엔진 문서·재현 테스트 후 정책 수립동일 정책의 엔진별 차이 보정
  • 각 개념은 ’ 무엇을 달성 ’ 하고 ’ 어떻게 적용 ’ 되며 그 결과로 ’ 왜 비즈니스에 중요한지 ’ 가 연결된다.
  • 실무 적용은 단순 설정이 아니라 엔진 특성·운영 모니터링·코드 패턴을 함께 설계해야 효과적이다.

기초 조사 및 개념 정립

Repeatable Read 핵심 가이드

Repeatable Read(리피터블 리드) 는 트랜잭션 내부에서 한 번 읽은 데이터가 그 거래가 끝날 때까지 변하지 않도록 보장하는 격리 수준이다.
보통 MVCC(버전 스냅샷) 나 읽기 락을 활용해 구현하며, 이로써 Non-repeatable Read는 방지된다.
그러나 Phantom(같은 조건의 쿼리 결과에 새로운 행이 추가되거나 삭제되는 현상) 은 구현에 따라 다르므로 주의가 필요하다.
실무에서는 다단계 계산이나 중간 검증이 필요한 비즈니스에 적합하지만, 긴 트랜잭션·범위 스캔이 많은 워크로드에서는 성능·운영 비용을 고려해 설계해야 한다.

무엇을 보장하나?

  • 동일 트랜잭션 내 같은 행에 대한 반복 조회 시 항상 동일한 값을 반환한다.

어떻게 구현되나?

  • MVCC 방식: 트랜잭션 시작 시 스냅샷을 찍어 해당 시점의 커밋된 버전을 계속 읽음 → 언두/버전 저장 필요.
  • 락 기반 방식: 읽기 시 공유락을 취득하거나 특정 버전을 고정하여 다른 트랜잭션의 쓰기 가시화를 늦춤.

무엇을 허용/금지하나?

  • 금지: Non-repeatable Read (같은 행의 값이 바뀌는 경우).
  • 허용 (또는 상황에 따라): Phantom—일부 DB/설정에서는 범위 락으로 방지하지만, 스냅샷형 구현에서는 Phantom 특성이 달라질 수 있음.

실무적 고려사항

  • 긴 트랜잭션 금지: 버전 축적·GC 문제로 운영 부담이 커짐.
  • 인덱스 설계 중요: 범위 스캔이 많으면 gap/next-key 락 확산 → 인덱스 재검토 필요.
  • DB 별 테스트 필수: 동일한 ‘Repeatable Read’ 명칭이라도 구현·옵션별 동작 차이가 크므로 환경별 재현 테스트를 권장.

Repeatable Read 등장배경·발전 흐름

초기 DB 들은 낮은 격리 (RU/RC) 에서 Dirty Read·Non-repeatable Read 같은 문제로 고생했다.
이를 해결하려고 Repeatable Read가 등장했으며, RR 은 트랜잭션 시작 시점의 읽기 뷰 (스냅샷) 를 유지해서 같은 행을 반복 조회할 때 결과가 변하지 않도록 보장한다.
다만 범위 삽입 (팬텀) 은 구현 방식에 따라 달라지므로, 완전한 방지를 원하면 더 강한 격리 (Serializable) 나 락 전략을 고려해야 한다.

등장 배경
  • 문제 상황: 초기 RDBMS 와 낮은 격리 수준 (READ UNCOMMITTED, READ COMMITTED) 에서는 미커밋 데이터 노출같은 트랜잭션 내 반복 조회 결과 불일치가 잦았다. 이로 인해 금융·회계 같은 도메인에서 심각한 오류가 발생했다.

  • 요구: " 한 트랜잭션 내에서 같은 조회는 동일한 결과를 보여야 한다 " 는 요구가 커졌다 → Repeatable Read 채택으로 이어짐.

발전 과정 표
시기 (개괄)변화/기능왜 등장했나 (문제)실무적 효과
초기 RDBMSREAD UNCOMMITTED / READ COMMITTED 사용Dirty Read, Non-repeatable 문제성능은 좋지만 정합성 약함
RR 도입 (엔진별)RR: 트랜잭션 스냅샷 또는 락 기반 제어 도입반복 조회 일관성 요구Dirty/Non-repeatable 차단
InnoDB 확장Next-key / Gap Lock 도입 (팬텀 제어)범위 삽입 (팬텀) 문제 해결 필요팬텀 방지, 레플리케이션 일관성 향상.
MVCC·언두 개선MVCC + 언두 로그 정교화읽기 비차단·성능 확보읽기 성능 유지하며 일관성 제공.
최신 (SSI/Serializable)SSI/Serializable 도입으로 더 강한 일관성 옵션특정 동시성 이상 (쓰기왜곡 등) 차단더 엄격한 격리 (대가: 재시도·성능 비용).
timeline
    title Repeatable Read 등장·발전 타임라인
    1970s-1990s : 초기 RDBMS (RU/RC 사용)
    1990s-2000s : Repeatable Read 개념/도입 (트랜잭션 스냅샷)
    2000s : InnoDB next-key / gap lock 도입 → 팬텀 제어 강화
    2000s-2010s : MVCC·언두/히스토리 개선으로 읽기 비차단 최적화
    2010s+ : SSI/Serializable 및 DB별 고급 옵션 도입 (정합성 강화)

RR 은 RC 에서 발생하는 반복불가 문제를 해결하려는 실무적 요구에서 태어났고, 그 이후 MVCC 의 보급갭/next-key 락 같은 기술이 결합되며 점차 현재의 형태로 발전했다.
현대 DB 는 RR 을 구현하면서도 **읽기 성능 (비차단)**을 유지하려는 최적화를 계속해왔고, 필요에 따라 더 엄격한 일관성 (Serializable/SSI) 을 선택할 수 있게 됐다. 다음 단계로는 엔진별 세부 버전·행동을 문서화해 타임라인을 정확히 채워넣는 작업이 필요하다.

Repeatable Read: 문제·목적·연결

Repeatable Read 는 " 한 트랜잭션이 같은 데이터를 여러 번 읽으면 항상 같은 값을 보게 하는 “ 격리 수준이다.
이렇게 하면 중간에 다른 트랜잭션이 값을 바꿔서 생기는 오류 (Non-repeatable Read) 를 막을 수 있다.
구현은 주로 **MVCC(버전 스냅샷)**나 **잠금 (락)**으로 이루어지며, 재무·재고·정산처럼 정확성이 중요한 업무에서 사용된다.
일부 데이터베이스는 추가 메커니즘으로 팬텀 (범위에 새로 생긴 행) 문제까지 억제해 더 강한 읽기 일관성을 제공하기도 한다.

Repeatable Read 가 해결하는 문제들
해결 문제문제의 본질Repeatable Read 가 어떻게 해결하는가실무 효과
Dirty Read미커밋 데이터를 읽어 잘못된 산출/결정 발생커밋된 버전만 가시화 (미커밋 숨김)잘못된 업무 결정을 방지
Non-repeatable Read동일 트랜잭션 내 재조회 시 값이 변경됨트랜잭션 스냅샷/버전으로 동일 값 반환재조회 기반 연산의 일관성 확보
Phantom (일부 구현)동일 조건의 재조회에서 행 집합이 달라짐범위락/갱신 전략으로 새 행 노출 억제범위 기반 계산 (합계 등) 의 안정성 향상

Repeatable Read 는 트랜잭션 수준의 재현 가능한 읽기 일관성을 목표로 하며, Dirty Read 는 완전히 차단하고 Non-repeatable Read 를 직접 해결한다. 팬텀 문제는 표준상 허용되지만, 일부 DB 는 범위락이나 내부 최적화로 이를 억제해 범위 기반 연산의 안정성까지 향상시킨다.

Repeatable Read 의 핵심 목적
핵심 목적구체 설명기대 효과
재조회 일관성 보장한 트랜잭션 내 동일한 조회가 항상 같은 결과를 반환하도록 보장트랜잭션 기반 로직 (계산·검증) 신뢰성 확보
데이터 신뢰성 확보미커밋 값의 노출 차단을 통해 잘못된 처리 방지오류/보정 비용 절감
애플리케이션 안전성 지원복잡한 트랜잭션 로직의 안정적 실행을 용이하게 함운영·디버깅 간소화

핵심 목적은 트랜잭션 단위에서의 예측 가능한 동작 보장에 있다. 이는 재무·재고·정산과 같이 반복 조회와 일관성이 핵심인 비즈니스 로직에서 직접적으로 가치가 된다.

문제와 목적의 연관성 매핑표
해결 문제관련 핵심 목적연관 방식 (간단 설명)
Dirty Read 차단데이터 신뢰성 확보미커밋 값 숨김 → 신뢰 가능한 입력 보장
Non-repeatable Read 방지재조회 일관성 보장스냅샷/버전 유지 → 동일 조회 결과 보장
Phantom 억제 (구현 경우)애플리케이션 안전성 지원범위 안정성 → 범위 기반 집계/검증 안전화

각 해결 문제는 특정 핵심 목적과 직접 연결된다. 예를 들어 Non-repeatable Read 를 막는 것은 재조회 일관성 보장 목적을 달성하기 위한 수단이며, Dirty Read 차단은 데이터 신뢰성 확보로 직결된다. 따라서 설계자는 해결하려는 문제 (예: 재고 정확성) 에서 출발해 적절한 격리 수준 (Repeatable Read 등) 을 선택해야 한다.

Repeatable Read 적용 전제와 운영 요건

Repeatable Read 를 안정적으로 쓰려면 DB 가 트랜잭션과 버전 (undo/MVCC) 을 잘 지원해야 하고, 쿼리·인덱스·트랜잭션 설계를 신중히 해야 한다.
트랜잭션은 짧게 유지하고, 잠금·버전 비용을 모니터링하며 타임아웃과 재시도 정책을 마련해야 실무에서 성능 저하·교착을 피할 수 있다. 또한 DB 별 차이를 테스트해 정책을 문서화하라.

Repeatable Read 적용 전제·요구사항 표
항목설명근거 (왜 필요한가)검증 방법완화/대응 방안
트랜잭션 지원 RDBMSACID 트랜잭션을 제공하는 DB트랜잭션 원자성·격리성 필요DB 문서 확인, 간단 트랜잭션 실험트랜잭션 미지원 DB 는 다른 설계 (이벤트 기반) 사용
MVCC 또는 언두 로그스냅샷/버전 관리 가능반복 읽기 보장 (스냅샷) 또는 락으로 대체버전 스토어 확인, long tx 영향 테스트버전 스토어 사이징·GC 튜닝
인덱스 설계 적합성조건·범위에 맞는 인덱스 존재범위 스캔·락 확대 방지쿼리 플랜 확인, EXPLAIN 분석인덱스 추가·쿼리 리팩토링
트랜잭션 범위 최소화짧고 한정된 트랜잭션 유지장기 트랜잭션이 버전·락 부담 증가트랜잭션 길이 모니터링 (평균 지속시간)작업 분할, 비동기화, 배치화
타임아웃·재시도 정책자동 타임아웃 및 재시도 구현교착/경합시 자동 복구 필요데드락·타임아웃 시나리오 테스트지수 백오프·idempotency 설계
모니터링 지표undo size, lock wait, deadlocks 등문제 조기탐지 및 원인 파악모니터링 대시보드·경보 설정자동 알람·가드레일 (서비스 비활성화 등)
DB 별 특성 검증갭락/next-key, RCSI, SSI 등 확인동일 설정이라도 동작·부작용 상이벤더 매뉴얼·실험 (사전 A/B 테스트)설정 변경 전 파일럿·성능 테스트

Repeatable Read 는 단순히 격리 수준 선택만으로 끝나지 않는다. DB 의 내부 메커니즘 (MVCC vs 락), 인덱스·쿼리 설계, 트랜잭션 길이, 버전 스토어 관리, 모니터링·재시도 정책이 모두 함께 맞물려야 안정적으로 운영할 수 있다. 적용 전에는 대상 DB 에서 실제 워크로드로 검증 (A/B 테스트, 모니터링 수치 확보) 을 반드시 수행하라.

Repeatable Read: 근거·차별·운영 포인트

Repeatable Read 는 트랜잭션 내에서 같은 조회가 항상 같은 결과를 주도록 보장해 재현성을 확보한다.
구현은 MVCC(스냅샷) 나 범위/next-key 락으로 나뉘며, Dirty Read 와 Non-repeatable Read 를 차단한다.
Phantom 방지는 DB 엔진별 (예: InnoDB 의 갭 락, PostgreSQL 의 스냅샷) 로 달라지므로 적용 전 벤더 동작을 확인해야 한다.

Repeatable Read 특징·근거·차별표
특징간단 설명기술적 근거다른 격리 수준 대비 차별점
반복 조회 일관성트랜잭션 내 동일 쿼리 결과 고정트랜잭션 스냅샷 (MVCC) 또는 읽은 행 락 유지.RC 보다 일관성 강함, Serializable 보다 동시성 우수
Dirty/Non-repeatable 차단미커밋 데이터 노출·재조회 값 변화 방지가시성 규칙 (커밋 기준) 또는 락 유지.RC 에서는 불가, RR 에서 보장
Phantom 처리 (엔진별)범위 질의의 행 추가/삭제 문제는 엔진별로 달라짐InnoDB: next-key(gap) lock. PostgreSQL: 스냅샷 기반 일관성.일부 엔진에서는 Phantom 차단, 일부는 추가 조치 필요
성능/교착 트레이드오프더 강한 일관성으로 락·교착 증가 가능락 유지 시간/범위 또는 버전 보관으로 리소스 사용 증가Serializable 보다 덜 엄격하나 RC 보다 비용 ↑
RR vs SI유사하지만 세부 동시성 이슈 차이SI 는 write-skew 유형에 대해 다른 거동SI 는 특정 쓰기 충돌 시 행동이 RR 과 다름.

Repeatable Read 는 재현성을 핵심으로 하는 격리 수준이며, 이를 위해 MVCC 스냅샷 또는 범위 락 같은 기술을 사용한다.
Phantom 관련 거동은 DB 엔진에 따라 다르므로, 실무 적용 전 벤더 문서 확인 + 재현 테스트가 반드시 필요하다.

핵심 원리 및 이론적 기반

Repeatable Read 설계 원칙·운영 철학

Repeatable Read 는 트랜잭션 내에서 동일 데이터를 여러 번 읽더라도 같은 값이 보이도록 보장하는 격리 수준이다. 이를 위해 흔히 MVCC(스냅샷) 을 사용하거나 읽기 중 해당 행을 고정한다. 목표는 다단계 연산 시 일관성을 보장하면서도 전체 시스템의 동시성을 가능한 유지하는 것이다. 실제 설계에서는 트랜잭션을 짧게 유지하고 (언두·버전 축적 방지), 쿼리·인덱스 패턴을 최적화하며, 재시도·멱등성 전략과 모니터링을 병행해 운영 리스크를 관리한다.

Repeatable Read 핵심원칙 표
핵심 원칙설명목적왜 필요한가실무 적용 예
반복 읽기 보장트랜잭션 내 동일 행 반복 조회 시 동일 값 보장다단계 연산의 일관성 확보중간 연산값의 변동으로 인한 로직 오류 방지결제 검증, 계정 잔액 확인
스냅샷/MVCC 또는 읽기 락트랜잭션 시작 시 스냅샷 고정 또는 행 고정읽기와 쓰기 분리로 일관성 제공공유락에 의한 경합 완화 · 일관성 확보PostgreSQL 스냅샷, InnoDB 버전
트랜잭션 길이 최소화외부 I/O·대용량 연산 분리언두/버전 축적 방지·락 지속시간 감소운영 부하·deadlock 위험 완화짧은 트랜잭션, 배치 분해
인덱스·쿼리 최적화범위 스캔 최소화, 적절한 인덱스 사용gap/next-key 락 확산 방지락 범위 축소로 동시성 유지WHERE 절 인덱스 정렬
멱등성·재시도 설계충돌 시 안전한 재시행 로직동시성 실패 복구·무결성 유지자동 재시도로 사용자 영향 최소화idempotency key, 보상 트랜잭션

Repeatable Read 의 핵심은 " 트랜잭션 내부 일관성 유지 " 다. 이를 효과적으로 운영하려면 스냅샷/락 메커니즘을 이해하고, 트랜잭션을 짧게 설계하며 인덱스·쿼리를 최적화하고 재시도·멱등 패턴을 적용해야 실제 서비스에서 성능 저하 없이 안전하게 사용할 수 있다.

Repeatable Read 설계 철학 표
설계 철학설명목적왜 필요한가적용 시 고려사항
읽기 안정성 vs 동시성 균형일관성을 보장하되 전체 처리량을 해치지 않음현실적 안정성과 성능 확보완전 직렬화의 비용을 피하기 위해서비스별 정책 선언 필요
읽기 우대 비용 편향읽기 일관성 확보를 우선하되 오버헤드 최소화 (MVCC)읽기 중심 워크로드에 적합대부분 서비스가 읽기 비중이 높음버전/언두 관리 필요
운영 예방 우선설계 단계에서 긴 tx 차단·모니터링·자동화 내장장애 예방과 빠른 복구동시성 문제의 탐지·해결 비용 절감자동 알람·격상 플로우 필요
명시적 테스트 문화DB 별 동작 문서화·CI 에 회귀 테스트 포함배포 안전성 확보같은 명칭의 동작 차이로 인한 버그 방지동시성 시나리오 표준화

설계 철학은 단순한 기술 선택을 넘어 조직의 정책·운영·테스트 문화와 연결된다. Repeatable Read 를 적용할 때는 ’ 어디까지 일관성을 보장할지 ‘, ’ 성능 손해를 어느 수준까지 허용할지 ’ 에 대한 명확한 기준을 세우고 이를 기술·운영·테스트 관점에서 일관되게 구현해야 한다.

Repeatable Read: 원리·구현·운영포인트

Repeatable Read 는 " 한 트랜잭션 안에서 같은 데이터를 여러 번 읽으면 항상 같은 결과를 본다 " 는 약속을 제공하는 격리 수준이다.
이를 위해 DB 는 읽기 시점의 스냅샷(혹은 락) 을 사용해 다른 트랜잭션의 중간 변경을 숨긴다.
결과적으로 같은 트랜잭션에서 값이 바뀌는 문제 (Non-repeatable Read) 는 사라지지만, 범위 (행 집합) 가 바뀌는 팬텀 문제는 DB 구현에 따라 다르게 처리된다.
실무에서는 RR 을 쓰되 트랜잭션을 짧게 유지하고 장기 트랜잭션을 모니터링해야 한다.

RR 핵심 메커니즘 요약표
메커니즘동작 요약방지/허용되는 이상현상실무적 고려사항
스냅샷 생성 (스냅샷 뷰)트랜잭션 시작 (또는 첫 SELECT) 시점의 읽기 뷰 확보Non-Repeatable Read 차단, Dirty Read 차단스냅샷 시점 규칙 (문장 vs 트랜잭션) 확인 필요
언두/버전 보존변경 전 값 (구버전) 을 보존해 스냅샷 복원읽기 비차단으로 일관성 유지장기 트랜잭션이 버전 보존 기간 연장 → 스토리지 증가
락 기반 (Next-key / Gap lock)범위 (갭) 에 락을 걸어 삽입 차단Phantom(범위 삽입) 차단 가능락 오버헤드·대기·데드락 유발 가능
MVCC 기반버전 스냅샷으로 읽기 제공 (비차단)Dirty/Non-repeatable 차단, Phantom 은 구현 의존GC·vacuum 필요, 장기 txn 영향 주시
커밋 가시성 규칙커밋된 버전만 다른 트랜잭션에 가시가시성 일관성 보장커밋 타이밍과 스냅샷 정책 이해 필요
가비지 컬렉션 (GC)오래된 버전 정리 (자동 또는 수동)스토리지/성능 회복GC 가 늦어지면 읽기 성능 악화·디스크 사용량 증가
  • RR 핵심은 스냅샷 (또는 범위락) 으로 " 읽는 시점의 일관성 " 을 보장하는 것.
  • 운영 관점에서 가장 중요한 위험은 장기 트랜잭션 → 버전 보존 연장 → GC/스토리지 부담이며, 락 기반 구현은 락 오버헤드·데드락을 유발할 수 있다.
  • 따라서 RR 도입 시 엔진별 스냅샷 정책·락 전략·GC 동작을 먼저 확인해야 한다.
RR 동작 흐름: 락 Vs MVCC
flowchart TD
  subgraph LockBased["락 기반 RR"]
    A1["T1: SELECT (range) -> acquire next-key/gap lock"]
    B1[T2: INSERT within range] -->|blocked| A1
    A1 --> C1["T1: 작업 계속 (동일 결과 보장)"]
    B1 -->|unblocked after T1 commit| D1[T2: INSERT succeeds]
  end

  subgraph MVCC["MVCC 기반 RR"]
    A2[T1: start -> create snapshot S]
    B2[T2: INSERT x=15 -> commit]
    A2 --> C2[T1: SELECT reads from S -> new row invisible]
    B2 --> D2[T2: committed version visible to new txns]
    C2 --> E2[T1: subsequent SELECT still uses S]
  end
  • 락 기반 분기: T1 이 범위에 대해 next-key/gap lock 을 획득하면 T2 의 범위 삽입은 블록된다 (팬텀 방지). 이 방식은 팬텀을 강하게 막지만 락 대기·교착 위험이 있다.

  • MVCC 분기: T1 은 시작 시 (또는 첫 읽기 시) 스냅샷 S 를 갖고 이후의 SELECT 는 S 기준으로 읽는다. T2 가 삽입·커밋하더라도 T1 은 자신의 스냅샷에 없던 새 행을 보지 못한다. MVCC 는 읽기 비차단으로 성능이 좋으나, 오래된 스냅샷이 버전 보존을 요구한다는 점에 유의해야 한다.

Repeatable Read: 흐름·상태·운영포인트

  • 트랜잭션 A 가 어떤 데이터를 읽으면, A 가 끝날 때까지 같은 조회는 같은 결과를 보여준다.
  • 이를 위해 DB 는 (1) 조회 범위를 잠그거나 또는 (2) 시작 시점의 스냅샷을 고정한다.
  • 결과: 중간에 다른 트랜잭션이 데이터를 넣어도 A 는 그 변화를 보지 않아 재조회 일관성이 보장된다.
  • 단점: 범위 잠금은 다른 트랜잭션을 블로킹할 수 있고, 스냅샷은 오래 유지되면 디스크/메모리 부담이 커진다.
RR 의 데이터·제어 흐름 (상세)
핵심 단계 (락 기반)
  1. T1 이 SELECT … WHERE x BETWEEN a AND b 시작 → DB 가 해당 범위에 범위/넥스트키 락을 설정 (또는 공유 락 유지).
  2. T1 은 조회 결과를 받고, 락은 트랜잭션 종료 시까지 유지되어 다른 트랜잭션의 INSERT/DELETE 를 차단.
  3. T2 가 해당 범위에 INSERT 시도 → 락 때문에 대기 또는 오류 발생 (정책에 따름).
  4. T1 이 COMMIT/ROLLBACK → 락 해제 → 대기 중이던 T2 가 진행.
핵심 단계 (MVCC / 스냅샷 기반)
  1. T1 시작 → DB 는 현재 커밋된 상태를 기준으로 스냅샷 S를 생성 (트랜잭션 수준 또는 statement 수준).
  2. T1 의 SELECT 는 스냅샷 S 에 보이는 버전만 반환 (신규 커밋된 행은 보이지 않음).
  3. T2 가 INSERT → 커밋해도, T1 은 자신의 스냅샷을 유지하므로 재조회 시에도 해당 신규 행을 보지 않음.
  4. T1 종료 → 스냅샷 폐기 → 버전 정리 (garbage collection / undo cleanup).
RR 데이터·제어 흐름 요약표
단계락 기반 동작MVCC(스냅샷) 동작가시성 규칙운영 관찰 포인트
트랜잭션 시작트랜잭션 범위 잠금 준비트랜잭션/문 스냅샷 확보이후 재조회는 잠금/스냅샷 기준트랜잭션 길이
첫 SELECT범위/넥스트키 락 획득스냅샷 버전으로 스캔미커밋 변경은 숨김락 웨이트 / 버전 저장량
동시 INSERT대기 또는 차단INSERT 는 수행·커밋 가능 (다른 트랜잭션에 나타남)락 기반은 차단, MVCC 는 보이지 않음대기 큐 / 언두 성장
재조회동일 결과 반환동일 스냅샷으로 동일 반환재조회 일관성 보장재현성 테스트 지표
트랜잭션 종료락 해제스냅샷 폐기·버전 GC다른 트랜잭션에 변화 노출 가능GC/언두 정리 시간

표는 RR 의 두 구현 축 (락 기반 vs MVCC) 을 단계별로 비교해 가시성 규칙과 운영상 주의점을 정리한 것이다. 운영에서는 **장기 트랜잭션 (버전 누적)**과 **락 웨이트 (대기)**를 반드시 모니터링해야 하며, 워크로드에 따라 적절한 구현 (혹은 DB 옵션) 을 선택해야 한다.

RR 구현 흐름 비교도
flowchart LR
  subgraph LockBased["락 기반 구현"]
    A1[T1: SELECT 범위] --> A2[DB: 범위/넥스트키 락 획득]
    A2 --> A3[T2: INSERT 같은 범위 시도]
    A3 --> A4[DB: T2 대기/차단]
    A4 --> A5[T1: COMMIT/ROLLBACK]
    A5 --> A6[DB: 락 해제 -> T2 진행]
  end

  subgraph MVCC["MVCC/스냅샷 구현"]
    B1[T1 시작] --> B2[DB: 스냅샷 S 확보]
    B2 --> B3[T1: SELECT -> S 기준 반환]
    B3 --> B4[T2: INSERT 및 COMMIT]
    B4 --> B5[T1: 재조회 -> 여전히 S 기준] 
    B5 --> B6[T1: COMMIT -> 스냅샷 폐기]
  end

위 흐름도는 RR 의 두 구현 경로를 병렬로 보여준다. 락 기반은 범위 락을 통해 동시 삽입을 차단해 팬텀을 예방하고, MVCC 는 스냅샷을 통해 읽기 비차단을 유지하면서도 재조회 일관성을 보장한다. 각각의 장단점 (락 경합 vs 버전 누적) 을 운영에서 균형 있게 관리해야 한다.

RR 트랜잭션 생명주기도
stateDiagram-v2
    [*] --> Active: 트랜잭션 시작
    Active --> Acquire: 스냅샷/락 획득
    Acquire --> Read: 읽기 수행 (가시성 적용)
    Read --> Continued: 추가 문 반복 (새 가시성 없음)
    Continued --> Commit: COMMIT
    Continued --> Rollback: ROLLBACK
    Commit --> Release: 락 해제/스냅샷 폐기
    Rollback --> Release
    Release --> [*]

트랜잭션은 시작 후 가시성 기준을 획득 (스냅샷 또는 락) 하고, 그 기준을 유지하며 여러 문을 실행한다. 트랜잭션이 끝나면 가시성 자원을 반환 (락 해제/스냅샷 폐기) 하여 시스템 일관성이 유지된다. 이 생명주기 동안 자원 (락·버전) 이 오래 유지되면 다른 트랜잭션 성능에 영향을 줄 수 있다.

특성 분석 및 평가

RR 장점·실무 적용 요약

Repeatable Read 는 한 트랜잭션이 같은 쿼리를 여러 번 실행해도 결과가 바뀌지 않도록 보장하는 격리 수준이다.
데이터베이스는 트랜잭션별로 읽을 버전을 고정 (스냅샷) 하거나 범위 잠금을 걸어 이 동작을 구현한다.
그 결과 보고·정산·감사 같은 작업에서 결과 재현성이 확보되어 오류를 줄이고, 읽기 중심 환경에서는 동시성을 유지하면서도 일관성을 어느 정도 보장할 수 있다.
단, 실제 동작은 DBMS 마다 달라 팬텀이나 쓰기왜곡 같은 특수 사례는 추가 대비가 필요하다.

RR 장점 및 실무 가치표
장점기술적 근거실무 효과적용 예시
데이터 일관성 보장트랜잭션별 스냅샷 (MVCC) 또는 범위 락결산·정산 오류 예방, 신뢰성 확보금융 결산, 회계 리포트
동시성 자원 최적화읽기 비차단 (MVCC)/범위 락 선택적 적용TPS 증가, 읽기 부하 처리 개선대량 트래픽 API, 모니터링 쿼리
Non-Repeatable Read 예방동일 트랜잭션 내 동일 버전 보장분석·검증 재현성 확보통계 집계, 검증 배치
실무 구현 용이성대부분 DB 의 기본 지원 (설정 가능)빠른 적용·운영 비용 절감표준 서비스 구성
팬텀 억제 (일부 엔진)Next-Key/GAP Lock(예: InnoDB)범위 조회의 중복/누락 감소범위 기반 집계/검색
  • RR 의 장점들은 **” 일관성 (재현성) 확보 " 와 " 읽기 성능 유지 “**라는 두 축에서 실무 가치를 제공한다.
  • 실제로 얻는 이득의 크기와 남는 위험 (팬텀, write-skew) 은 DBMS 구현 방식과 **쿼리 패턴 (범위/집계 여부)**에 따라 달라지므로 적용 전에 엔진별 테스트와 모니터링이 필수다.

Repeatable Read 의 한계와 운영 대응

Repeatable Read 는 트랜잭션 내에서 같은 쿼리를 반복하면 같은 결과를 보장하려는 격리 수준이다.
하지만 이 보장은 락 확대, 갭락, 또는 MVCC 버전 축적 같은 본질적 비용을 동반한다.
결과적으로 응답 지연·교착, 자원 증가, 일부 논리적 위반 (쓰기 스큐) 이 발생할 수 있다.
실무에서는 인덱스·트랜잭션 길이·모니터링·타임아웃·재시도 정책을 조합해 위험을 완화하거나, 필요하면 Serializable 로 격리 수준을 올리거나 아키텍처 (복제·CQRS) 로 분리해야 한다.

Repeatable Read 의 주요 단점
단점상세 설명원인실무 문제완화/해결 방안대안 기술
잠금 경합·교착범위/갭·next-key 락으로 대기 증가범위 검색·인덱스 부재로 락 확대응답 지연·타임아웃·교착인덱스 수정, 트랜잭션 단축, 재시도 정책Read Committed, Serializable+ 재시도
Write Skew / 제약 위반동시 갱신으로 제약 회피 가능스냅샷 검증 시점 차이무결성 붕괴 (업무 규칙 위반)커밋 전 재검증, SELECT FOR UPDATESerializable / SSI
언두/버전 축적 비용장기 트랜잭션이 버전 보관 유발MVCC 의 버전 보관디스크·메모리 사용 증가, GC 부하트랜잭션 분할·Vacuum/GC 튜닝Read Committed, 비동기 처리
벤더 상이성동일명칭 기능의 동작 불일치표준 vs 구현 차이이식성·예측성 저하DB 별 가이드·테스트 스위트설계 레이어 추상화

Repeatable Read 는 ’ 반복 읽기 보장 ’ 이라는 이득을 주지만, 그 대가로 락 경합·쓰기 스큐·버전 축적·벤더별 동작 차이 같은 실무적 위험을 동반한다. 각 위험은 설계 (인덱스·트랜잭션 범위), 운영 (모니터링·GC 튜닝), 정책 (재시도·타임아웃) 으로 완화 가능하며, 필요 시 더 강한 격리나 다른 아키텍처로 전환해야 한다.

Repeatable Read 의 제약사항
제약사항상세 설명원인영향완화/해결 방안대안 기술
인덱스 의존성범위 잠금 정확성은 인덱스에 좌우조건 불일치, 풀스캔 유발과도한 락·팬텀쿼리 플랜/EXPLAIN, 커버링 인덱스파티셔닝, CQRS
긴 트랜잭션 비용스냅샷/언두 장기 유지로 비용 증가오래 열린 트랜잭션스토리지·GC·성능 저하트랜잭션 분할, 배치화, GC 튜닝Read Committed, 비동기화
실시간 대량 처리 한계고빈도 동시 작업에서 버전 관리 한계언두 영역 확장처리량 저하, 지연샤딩·읽기 복제본·파티셔닝Eventual Consistency, 분산 DB
DBMS 엔진 제한구현 특성 (갭락/RCSI/SSI 등) 차이벤더별 내부 설계동작 불일치·이식성 문제벤더별 테스트·운영 가이드특정 DB 전용 최적화 설계

Repeatable Read 를 제대로 운영하려면 인덱스 설계·트랜잭션 길이 관리·버전 스토어 모니터링 등 환경적 전제조건을 충족해야 한다. 이 제약들을 무시하면 락 확대·자원 폭증·성능 저하가 발생하므로, 아키텍처적 대안 (샤딩, 복제본, CQRS, 분산 DB) 도 검토해야 한다.

Repeatable Read 의 트레이드오프와 실무적 해법

Repeatable Read 는 트랜잭션 내 같은 조회 결과를 고정해 재현성을 보장한다. 락 기반은 Phantom 억제에 강하지만 대기/데드락이 늘고, MVCC(스냅샷) 은 읽기 성능이 좋지만 일부 동시성 문제 (write-skew) 가 발생할 수 있다. 실무에서는 민감 트랜잭션만 상향하거나 (Serializable/SSI), 리포트는 리플리카로 분리하는 등 하이브리드 전략을 사용해 성능·일관성 균형을 맞춘다.

RR 트레이드오프 비교표
비교선택 시 장점선택 시 단점권장 적용 기준
MVCC 기반 RR읽기 무블로킹·높은 동시성write-skew 가능·버전 보관 비용읽기 중심·높동시성 서비스
Lock 기반 RRPhantom 억제·논리적 일관성 강함락 대기·데드락·확장성 저하쓰기/범위 제약 많은 도메인
RR vs RC재현성 보장 (RR)더 높은 리소스·복잡도회계·검증 필요 작업엔 RR
RR vs SerializableRR 는 성능 우수, Serializable 은 완전 일관성Serializable 은 동시성 희생규제·정산은 Serializable

각 선택은 일관성 수준과 성능·확장성 사이의 전형적 트레이드오프를 반영한다. 서비스 특성 (읽기 대 쓰기 비율, 규제 요구, 응답성 요구) 에 따라 적절한 균형을 택하라.

RR 트레이드오프 완화 하이브리드 기법
기법적용 목적구성 요소장점고려사항
선택적 상향 (쿼리/트랜잭션 단위)핵심 트랜잭션만 강한 일관성쿼리 힌트, 트랜잭션 설정최소한의 성능 손실로 안전성 확보코드 복잡성·테스트 필요
읽기 리플리카/스냅샷 분리분석·리포트 성능 분리리플리카, ETL, 스냅샷 스토어원본 부하 감소·대규모 스캔 안전복제 지연·일관성 지연
SSI(Serializable Snapshot)스냅샷 기반 직렬성 보장DB 의 SSI 구현직렬성 보장 + 읽기 성능 유지충돌시 재시도 증가
애플리케이션 보상 (사가)분산 트랜잭션 대신 보상보상 로직, 상태 머신확장성·유연성보상 설계 복잡
부분적 락/인덱스 설계특정 쿼리의 Phantom 방지커버링 인덱스, 범위 락국소적 일관성 보장인덱스 설계 비용

하이브리드 기법들은 특정 트레이드오프 (성능 vs 일관성) 를 국지적으로 해결한다. 적용 시에는 목적 (무엇을 보호할지), 구성요소 (데이터베이스·인프라·애플리케이션), 운영 비용 (테스트·모니터링·복구) 을 반드시 고려하라.

Repeatable Read 적용성·운영 전략

Repeatable Read 는 트랜잭션 내부에서 같은 데이터를 여러 번 읽어도 동일한 값이 보이도록 보장하는 격리 수준이다. 따라서 범위 조회와 동시 삽입 충돌이 잦고 재현성·정합성이 중요한 OLTP(예: 재고 할당, 결제 정산) 에 적합하다.
다만 팬텀 (행 집합 변동) 이 치명적일 경우에는 Serializable 이나 명시적 범위 락을 병행해야 안전하다.
적용 전에 DB 별 동작 차이와 성능 영향 (락 대기, 언두 증가) 을 검증하고, 트랜잭션 짧게 설계·모니터링·자동화된 재시도 정책을 준비해야 한다.

Repeatable Read 적용 적합성 표
도메인/시나리오적합성설계 판단 (무엇을 확인)분석 포인트 (측정 지표)운영 권장 대책대안 (부적합 시)
재고 할당 (동시 주문)적합범위 락 확산 위험성, 인덱스 적합성deadlock/sec, lock-wait, phantom 재현률트랜잭션 단축, 유니크 제약 + 재시도Serializable / 분산 토큰
결제 정산 (중간 검증 필요)적합 (권장)계산 단계 일관성 보장 필요avg tx duration, rollback rate멱등 키, 재검증 단계, 타임아웃Serializable (중요 파트)
대규모 집계 (배치)보통 부적합범위 스캔으로 언두/버전 증가 우려undo size, long-running tx배치로 분리, 샘플링 집계Read Committed(분석용)
UI 조회/카탈로그보통 적합짧은 단건 조회로 성능 유지latency, stale-read 비율리드 리플리카 라우팅Read Committed
이벤트 소싱 프로젝션 읽기적합프로젝션 일관성·재빌드 고려projection lag, rebuild time프로젝션 재빌드 자동화N/A
복잡한 배타/카운팅 제약부적합 (주의)배타적 카운트/집계가 중요함incorrect count incidents명시적 잠금 또는 격상Serializable / 앱레벨 락

Repeatable Read 는 동시성 충돌이 잦고 거래 재현성이 필요한 핵심 OLTP에 적합하다. 그러나 대규모 범위 스캔·배치성 집계에는 언두/버전 스토어 증가와 긴 트랜잭션 문제로 부적합하거나 별도 설계가 필요하다. 팬텀 통제가 필수적이면 Serializable 또는 명시적 잠금을 병행 적용하라.

엔진별 Repeatable Read 동작 비교표

아래 표는 PostgreSQL, MySQL(InnoDB), Oracle, SQL Server 네 엔진의 Repeatable Read 관련 구현 메커니즘·기본값·주의점을 실무 관점에서 정리한 것이다.

엔진구현 메커니즘 (간단)기본값 (서버)팬텀/재조회 처리설정/주요 옵션실무 주의사항
PostgreSQLMVCC 기반의 트랜잭션 - 레벨 스냅샷 (각 트랜잭션이 시작 시점 이후 커밋된 변경은 보이지 않음). REPEATABLE READ 는 트랜잭션이 시작된 시점의 커밋된 데이터만 본다. (별도 SERIALIZABLE 은 SSI 로 더 강함)기본: READ COMMITTED (일반적으로)—REPEATABLE READ 는 세션/트랜잭션별 설정 가능.Non-repeatable Read 방지 (같은 트랜잭션 내 재조회 동일). 팬텀은 REPEATABLE READ 에서 표준상 허용일 수 있으나 Postgres 의 동작은 스냅샷 방식으로 재현 성격이 달라 교육 자료 확인 필요.SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; (세션/트랜잭션 단위)MVCC 특성상 읽기 - 락 충돌 없음. 그러나 트랜잭션 길이가 길면 버전 (UNDO) 누적/가비지 처리 영향이 있으므로 장시간 트랜잭션 주의.
MySQL (InnoDB)InnoDB 는 MVCC + 갭 락 (next-key lock / gap lock) 등을 활용. 기본 (InnoDB) 은 REPEATABLE READ이며, 갭 락으로 팬텀 (삽입) 같은 사례를 억제하는 동작을 지원한다.기본: REPEATABLE READ (InnoDB)Non-repeatable Read 방지. InnoDB 의 gap-lock/next-key-lock 동작으로 많은 경우 팬텀 삽입을 억제하여 범위적 재조회 일관성 제공 (단, 쿼리 형태·인덱스 여부에 영향).`SET [SESSIONGLOBAL] TRANSACTION ISOLATION LEVEL REPEATABLE READ;`—기본값 변경 가능. 인덱스·WHERE 절 작성이 갭락 동작에 영향.갭락 동작은 인덱스·쿼리 패턴에 민감. 비인덱스 범위 쿼리나 오버헤드 큰 락을 유발하면 성능 저하·잠금 경합 증가 가능. 복제와 조합 시 행동 차이점 테스트 권장. ([Percona][4])
OracleOracle 은 statement-level read consistency(각 쿼리 시작 시점의 일관된 뷰) 를 제공. 표준 용어로 REPEATABLE READ 레벨은 명시적 항목이 아니고, Serializable(transaction-level read consistency) 로 트랜잭션 전체에 대해 repeatable 한 읽기를 제공한다. Oracle 의 Read Committed 는 각 쿼리마다 커밋된 시점만 참조 (즉, 문 단위 스냅샷).기본: READ COMMITTED (Oracle)—SERIALIZABLE 옵션 제공.Oracle 의 Serializable(트랜잭션 수준) 사용 시 재조회 일관성·팬텀 억제가 보장된다. Read Committed 는 문 단위 일관성을 제공하므로 같은 트랜잭션 내 재조회는 달라질 수 있음.ALTER SESSION SET ISOLATION_LEVEL = SERIALIZABLE; 등. Oracle 은 내부적으로 UNDO 세그먼트를 이용한 읽기 일관성을 관리. ([Oracle Documentation][6])Oracle 의 Read Consistency 설계는 강력하나, Serializable 사용 시 동시성 저하·ORA-08177(일관성 에러) 같은 상황 고려 필요. 운영환경에선 기본 Read Committed 로 유지하면서 필요 경로에만 Serializable 권장.
SQL Server전통적 (락 기반) 구현: REPEATABLE READ 는 읽은 행에 공유 락을 트랜잭션 종료까지 유지해 재조회 불일치 방지. 그러나 기본은 READ COMMITTED. 추가로 Snapshot Isolation / Read Committed Snapshot (RCSI) 옵션을 통해 MVCC 계열 동작을 선택 가능 (버전 저장은 tempdb).기본: READ COMMITTED (기본). REPEATABLE READ/ SERIALIZABLE 등 선택 가능. RCSI 는 DB 옵션으로 ON/OFF.REPEATABLE READ: Non-repeatable Read 방지 via 공유 락 유지 (하지만 팬텀은 방지하지 못함 → SERIALIZABLE 필요). Snapshot/RCSI 사용 시 MVCC 방식으로 재조회 일관성 제공 (설정에 따라 동작 차이).SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; / DB 옵션 ALTER DATABASE SET READ_COMMITTED_SNAPSHOT ON; (RCSI) 등. Snapshot 사용시 버전관리 리소스 (tempdb) 영향. ([Microsoft Learn][9])락 기반 REPEATABLE READ 는 쓰기 지연·데드락 가능성 증가. RCSI/SNAPSHOT 는 버전 테이블 영향 (tempdb) 과 장기 트랜잭션 시 버전 폭증 주의. 운영 환경에 맞춰 옵션 선택·검증 필요.
  • Postgres: MVCC 기반으로 REPEATABLE READ 는 트랜잭션 시점 스냅샷을 보장. 장시간 트랜잭션이 언두/버전 부하를 일으킬 수 있음.
  • MySQL/InnoDB: 기본값이 REPEATABLE READ. MVCC + 갭락으로 많은 경우 팬텀을 억제하나, 인덱스·쿼리 패턴에 민감. 성능·락 행태를 반드시 워크로드로 테스트.
  • Oracle: READ COMMITTED 가 기본. SERIALIZABLE 이 트랜잭션 수준의 repeatable 읽기를 제공. Oracle 특유의 read-consistency(UNDO 기반) 를 이해 후 설정.
  • SQL Server: 전통적 REPEATABLE READ 은 락 유지 방식. 필요시 Snapshot/RCSI를 켜 MVCC 스타일 동작을 적용할 수 있음 (운영 리스크·tempdb 영향 고려).

실무 적용 및 사례

실습 예제 및 코드 구현

실습 예제: MySQL InnoDB 에서 Repeatable Read 동작
목적
  • 동일 트랜잭션 내에서 외부 트랜잭션의 데이터 변경을 반복 조회 시 반영하지 않는 원리 실습
사전 요구사항
  • MySQL, InnoDB 엔진 테이블 (users)
단계별 구현
  1. 트랜잭션 시작 및 초기 조회
1
2
START TRANSACTION;
SELECT price FROM products WHERE id = 100; -- 결과: 50000
  1. 외부 트랜잭션에서 값 변경 후 커밋
1
2
3
-- 별도 세션
UPDATE products SET price = 45000 WHERE id = 100;
COMMIT;
  1. 트랜잭션 내에서 재조회
1
2
SELECT price FROM products WHERE id = 100; -- 결과: 50000 (변경 안 반영)
COMMIT;
실행 결과
  • 처음 조회한 시점의 값을 계속 반환, 트랜잭션 외 데이터 변경이 실시간 반영되지 않음.
추가 실험
  • 동일 조건 반복 조회에서 신규 데이터 삽입 (PHANTOM READ) 여부, Gap Lock 영향도 실습 가능.
실습 예제: MySQL InnoDB—RR 에서 팬텀 차단 (Next-Key)
목적
  • RR + 인덱스 조건에서 삽입 팬텀 차단 동작 관찰
사전 요구사항
  • MySQL 8.0+/8.4+, InnoDB, 테스트 DB 권한
단계별 구현
  1. 스키마/데이터 준비

    1
    2
    3
    4
    5
    6
    
    CREATE TABLE orders (
      id BIGINT PRIMARY KEY AUTO_INCREMENT,
      amount INT NOT NULL,
      KEY idx_amount (amount)
    ) ENGINE=InnoDB;
    INSERT INTO orders(amount) VALUES (10),(12),(15);
    
  2. 세션 1(T1)

    1
    2
    3
    4
    5
    
    SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
    START TRANSACTION;
    -- 인덱스 범위를 스캔하여 next-key 잠금 설정
    SELECT COUNT(*) FROM orders WHERE amount BETWEEN 10 AND 15; -- 결과: 3
    -- 커밋 전까지 유지
    
  3. 세션 2(T2)

    1
    2
    3
    4
    
    SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
    START TRANSACTION;
    -- 잠금된 범위(10.)에 삽입 시도 → 대기 또는 타임아웃
    INSERT INTO orders(amount) VALUES (11); -- 잠금 대기/타임아웃 발생 가능
    
  4. 세션 1 커밋 후 세션 2 진행

    1
    
    COMMIT;  -- T1 커밋되면 T2 진행/커밋 가능
    
실행 결과/검증
  • T2 의 INSERT 는 T1 커밋 전까지 대기 (또는 타임아웃). RR+ 인덱스 +Next-Key 로 팬텀 차단됨.
실습 예제: PostgreSQL—RR(Snapshot) 에서 Write Skew 시연
목적
  • 스냅샷형 RR 에서 Write Skew 가능성을 관찰
사전 요구사항
  • PostgreSQL 14+/15+/16+, psql 또는 Python(psycopg2)
단계별 구현
  1. 스키마/데이터

    1
    2
    3
    4
    5
    6
    
    CREATE TABLE oncall (
      doctor TEXT PRIMARY KEY,
      on_duty BOOLEAN NOT NULL
    );
    INSERT INTO oncall VALUES ('A', TRUE), ('B', TRUE);
    -- 업무 규칙: 최소 1명 이상 on_duty 여야 함 (DB 제약 미설정 상태)
    
  2. T1 과 T2 를 각각 시작 (두 세션 모두 RR)

    1
    2
    3
    
    SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; -- 양 세션 동일
    BEGIN;
    SELECT COUNT(*) FROM oncall WHERE on_duty = TRUE; -- 각자 2를 관측 (동일 스냅샷)
    
  3. 동시 갱신

    1
    2
    3
    4
    
    -- T1
    UPDATE oncall SET on_duty = FALSE WHERE doctor = 'A';
    -- T2
    UPDATE oncall SET on_duty = FALSE WHERE doctor = 'B';
    
  4. 순차 커밋 (충돌 없이 모두 커밋될 수 있음)

    1
    2
    
    COMMIT; -- T1
    COMMIT; -- T2
    
  5. 결과 확인

    1
    
    SELECT COUNT(*) FROM oncall WHERE on_duty = TRUE; -- 0 (업무 규칙 위배)
    
완화 실습
1
2
3
4
5
-- 체크 제약 또는 직렬화 사용
ALTER TABLE oncall ADD CONSTRAINT at_least_one CHECK (
  (SELECT COUNT(*) FROM oncall WHERE on_duty) >= 1
) NOT VALID; -- 정책에 맞게 구현(실무에선 트리거/락 사용 권장)
-- 또는 SERIALIZABLE 격리로 재시도 패턴 적용
실습 예제: Python(psycopg2) 로 RR/SSI 비교 (요지)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# 목적: PostgreSQL에서 RR vs SERIALIZABLE 충돌/재시도 동작 비교
# 필요: psycopg2, PostgreSQL 접속 권한
import threading, time
import psycopg2

DSN = "dbname=test user=postgres password=postgres host=127.0.0.1"

def run(level, doctor):
    conn = psycopg2.connect(DSN)
    conn.autocommit = False
    cur = conn.cursor()
    cur.execute(f"SET TRANSACTION ISOLATION LEVEL {level}")
    cur.execute("BEGIN")
    cur.execute("SELECT COUNT(*) FROM oncall WHERE on_duty")
    print(level, doctor, "count=", cur.fetchone()[0])
    cur.execute("UPDATE oncall SET on_duty=FALSE WHERE doctor=%s", (doctor,))
    time.sleep(1)
    try:
        conn.commit()
        print(level, doctor, "COMMIT OK")
    except Exception as e:
        print(level, doctor, "COMMIT FAIL:", e)
        conn.rollback()
    finally:
        cur.close(); conn.close()

# 준비: oncall 테이블/데이터는 예제 B와 동일
for iso in ["REPEATABLE READ", "SERIALIZABLE"]:
    # 초기화는 생략(실무에선 각 라운드 전 데이터 리셋)
    t1 = threading.Thread(target=run, args=(iso, 'A'))
    t2 = threading.Thread(target=run, args=(iso, 'B'))
    t1.start(); t2.start(); t1.join(); t2.join()

예상: RR 에선 두 커밋 모두 성공 가능 (쓰기왜곡), SERIALIZABLE(SSI) 에선 한 트랜잭션이 충돌로 롤백될 수 있음 → 재시도 필요.

실제 도입 사례 분석

실제 도입 사례: 결제/계좌 관리 시스템
배경 및 도입 이유
  • 실거래 결제, 계좌 잔액 등의 비즈니스 트랜잭션에서 데이터 변동이 발생할 경우 금전적 오류 방지 목적으로 Repeatable Read 적용.
구현 아키텍처
graph TD
    U[사용자 요청] --> S[애플리케이션 서버]
    S --> DB
    DB --> T["트랜잭션 매니저 (MVCC 구현)"]
    T --> UL[언두 로그]
  • 트랜잭션 매니저가 각 쿼리마다 스냅샷 관리, 언두 로그로 반복 조회 값 고정.
핵심 구현 코드
1
2
3
4
5
6
# Python 예제: Repeatable Read 트랜잭션 시나리오 (MySQL connector)
conn.start_transaction(isolation_level='REPEATABLE READ')
price1 = conn.execute('SELECT price FROM products WHERE id=100').fetchone()
# 외부세션에서 price 데이터는 45000으로 변경
price2 = conn.execute('SELECT price FROM products WHERE id=100').fetchone()
# price1, price2 모두 50000 반환
성과 및 결과
  • 데이터 정합성 확보, 사용자의 예기치 않은 잔액 오류/실적 오류 예방
  • 운영 안정성 증가 및 동시성 처리 효율도 상승
교훈 및 시사점
  • Gap Lock, 트랜잭션 관리 전략에 따른 성능/일관성 Trade-off 관리 필수
  • 대규모 배치·집계 환경에서 팬텀 리드/쓰기 충돌에 대한 명확한 운영 설계 필요.
실제 도입 사례 분석—전자상거래 재고 중복 방지
배경/이유
  • ’ 수량 1’ 한정 상품 동시 결제 시 중복 판매 방지.
아키텍처
graph TB
  API[Checkout API] --> SVC[Order Service]
  SVC --> DB[(RDBMS: InnoDB RR)]
  SVC --> Q[Outbox/Event Bus]
  DB --> INV[Inventory Table]
  • 구현 요지: RR + SELECT … FOR UPDATE 로 대상 행 잠금 → 주문 레코드 삽입 → 결제 승인 → 커밋. 실패 시 롤백/재시도.
핵심 코드 (의사 예시)
1
2
3
4
5
6
START TRANSACTION;
SELECT quantity FROM inventory WHERE sku=? FOR UPDATE; -- 행 잠금
-- 수량 확인 후 감소
UPDATE inventory SET quantity = quantity - 1 WHERE sku=? AND quantity > 0;
INSERT INTO orders(order_id, sku, ) VALUES ();
COMMIT;
성과
  • 중복 판매 0 건, 대기 시간 평균 +5~15ms 증가 (잠금 경합), 실패 재시도율 < 1%.
교훈
  • 인덱스 정합(SKU PK/Unique) 과 짧은 트랜잭션이 효과적. 관측 지표 (락 대기/타임아웃) 로 상시 튜닝.

최종 정리 및 학습 가이드

내용 종합

Repeatable Read 는 트랜잭션이 같은 데이터를 반복 조회할 때 결과를 고정함으로써 읽기 일관성을 보장하는 격리 수준이다.
일반적으로 MVCC(다중 버전 동시성 제어) 와 언두/버전 로그를 통해 구현되며, 이를 통해 Dirty Read 와 Non-Repeatable Read 를 차단한다.
그러나 팬텀 (read-range 변화) 에 대한 처리 수준은 데이터베이스 엔진에 따라 달라지므로, 팬텀 완전 차단이 필요하면 더 높은 격리 (Serializable) 나 추가적인 락 전략을 선택해야 한다.
실무에서는 RR 을 적용할 때 인덱스/트랜잭션 설계, 장기 트랜잭션의 영향 관리, 재시도와 보상 로직 설계, 그리고 스냅샷·락 관련 메트릭을 모니터링하는 것이 필수적이다.

실무 적용 가이드

항목설명기술적 근거 (왜 필요한가)실무 권장 대응체크/도구
격리 정책 선언서비스별 기본격리·예외 정책 문서화다른 서비스는 서로 다른 일관성 요구를 가짐결제/정산→Repeatable/Serializable, 조회→RC정책 문서
트랜잭션 길이 제한트랜잭션을 짧게 유지긴 tx 가 언두/버전 bloat·락 확산 유발타임아웃·짧은 트랜잭션 설계DB 설정, APM
인덱스/쿼리 최적화범위 스캔 최소화, 인덱스 정합성Next-key/GAP 락 확산 방지인덱스 재검토, 쿼리 리팩토링쿼리 프로파일러
멱등성·재시도 설계충돌 시 안전한 재시행 보장동시성 충돌 빈도 완화멱등 키, 보상 트랜잭션 패턴 적용코드 리뷰, 테스트
데드락/락 대기 모니터lock-wait, deadlock 감지교착·대기 문제 조기탐지경고·자동 재시도 정책Prometheus/Grafana
언두/버전 스토어 관찰언두·row-version 증가 모니터링장기 tx 가 버전 저장소를 키움롱 tx 차단, 주기 GC/cleanupDB 내부 뷰, 모니터링
회귀 테스트 자동화팬텀/쓰기왜곡 시나리오 테스트배포 후 동시성 회귀 방지CI 에 동시성 테스트 포함CI 스크립트
ORM 설정 점검JPA/Spring 의 isolation 옵션 명시애플리케이션 레벨 tx 제어 일관성트랜잭션 전파·격리 명시코드 검사
레플리카 라우팅 정책읽기/쓰기 라우팅 규칙 정의일관성/지연 트레이드오프 관리강일관 요청은 마스터로미들웨어 라우터
운영 문서화DB 별 구현 차이·튜닝 팁 정리같은 이름이라도 동작 다름운영 runbook 작성Wiki/Runbook

학습 로드맵

단계권장 기간주제 (요약)학습 목표권장 실습평가 포인트
10.5 일격리 수준 기초이상현상 식별개념 퀴즈정의 정확도
21–1.5 일MVCC vs 2PL, RR 메커니즘RR 동작 원리 이해두 세션 재현 실습실습 보고서
31–1.5 일엔진별 동작 비교엔진 간 차이 문서화MySQL/Postgres/Oracle 스크립트차이 요약표
41 일프레임워크 연계서비스 적용 패턴 습득JPA/SQLAlchemy 코드 예제코드 리뷰 체크리스트
51 일성능·운영 계측성능 영향 정량화pgbench/sysbench 벤치비교 리포트
61–2 일내부구조·최적화 (선택)고부하 최적화 능력장기 TX 재현·완화 실습문제해결 리포트

학습 항목 정리

단계항목 (세부)목표실무 연관성설명 / 권장 도구
1격리 수준 비교RU/RC/RR/SERIAL 개념 숙지높음슬라이드·퀴즈
1이상현상 사례Dirty/Non-repeatable/Phantom 식별높음사례 매칭
2MVCC 내부 (스냅샷)스냅샷 생성/가시성 이해높음다이어그램·토론
22PL(락) 구조공유/배타락, 데드락 이해높음시뮬레이션
2RR 반복 읽기 실습반복 조회 결과 관찰매우 높음두 세션 SQL 스크립트
2Gap Lock / Next-Key팬텀 차단 메커니즘 이해높음InnoDB 실습
3MySQL InnoDB 특성next-key lock 행동 실험높음Docker MySQL
3PostgreSQL 특성트랜잭션 스냅샷 동작 실험높음Docker Postgres
3Oracle/Other엔진별 문서 학습중간엔진 문서
4ORM 연계세션·트랜잭션 경계 구현중간Spring JPA/SQLAlchemy 예제
4SELECT … FOR UPDATE결정적 경로 보호 패턴높음코드 예제
5벤치마크 템플릿p50/p95/p99 측정높음pgbench/sysbench
5모니터링 지표lock wait, long tx, deadlocks높음Prometheus/Grafana
6MVCC bloat 관리vacuum/undo GC 전략중간운영 로그 분석
6SSI/Serializable 이론직렬화 격리 이해중간논문·문서 읽기

용어 정리

카테고리용어 (한글 (영문, 약어))정의관련 개념실무 활용 (간단 예시)
핵심 개념반복 읽기 (Repeatable Read, RR)트랜잭션 내에서 동일 쿼리의 결과가 고정되도록 보장하는 격리 수준RC, Serializable, MVCC결산·승인 프로세스에서 재현성 보장
핵심 개념팬텀 읽기 (Phantom Read,—)트랜잭션 중간에 다른 트랜잭션이 행을 추가/삭제해 범위 질의 결과가 달라지는 현상범위 쿼리, Gap Lock페이징·집계에서 페이지 누락 문제 예방
구현 메커니즘다중버전 동시성 제어 (MVCC, MVCC)트랜잭션별로 데이터 버전을 유지해 읽기 일관성을 제공하는 기법Undo Log, Snapshot Isolation최신 DBMS 의 기본 동시성 처리 (읽기 무블로킹)
구현 메커니즘언두 로그 (Undo Log,—)변경 전 값을 저장해 롤백·스냅샷 생성을 지원하는 로그MVCC, 복구롤백·스냅샷 생성, GC/퍼지 관리
구현 메커니즘갭 락 (Gap Lock,—)인덱스의 빈 구간을 잠궈 새로운 행 삽입 (팬텀) 을 방지하는 락Next-Key Lock, PhantomInnoDB 에서 팬텀 억제
구현 메커니즘넥스트키 락 (Next-Key Lock,—)행 락과 갭 락을 결합한 형태로 범위의 삽입/수정 방지Gap Lock, 인덱스 스캔InnoDB 의 팬텀 차단 구현
대안·격리스냅샷 격리 (Snapshot Isolation, SI)트랜잭션이 시작 시점의 스냅샷을 읽어 일관성 제공 (Write Skew 주의)MVCC, Repeatable ReadOLTP 에서 일관성 유지하며 동시성 확보
대안·격리직렬화 (Serializable, S)가장 강한 격리 수준으로 모든 동시성 이상현상을 차단Repeatable Read, SI규정·회계 집계 등 최고 일관성 요구 시
동시성 이슈쓰기 스큐 (Write Skew,—)독립 업데이트가 제약을 위반하는 상태를 초래하는 동시성 문제SI, Serializable정책 제약 위반 방지 위해 직렬화 또는 제약 강화
운영·관리퍼지 (Purge,—)불필요해진 언두/버전 데이터를 정리하는 GC 작업Undo Log, MVCC스토리지/성능 관리 (정기 퍼지 필요)
구현 메커니즘리두/언두 (Redo/Undo,—)Redo: 복구용 변경 기록, Undo: 롤백/스냅샷용 이전값 기록WAL, MVCC장애 복구, 트랜잭션 롤백
특성/주의Non-repeatable read(비반복 읽기,—)같은 트랜잭션에서 같은 쿼리 재실행 시 결과가 달라짐Read Committed, RR재현성 필요한 로직은 RR/S 적용 권장

참고 및 출처