MVCC로 읽기와 쓰기를 함께 처리하는 방법

MVCC의 버전 관리 원리와 MGA, Rollback Segment, SCN 기반 읽기 일관성을 정리하고 운영 시 고려할 점을 설명한다.

2026-08-14 · 최초 발행 2025-08-10

잠금 대기 없이 읽기 일관성을 만드는 방식

동시에 많은 트랜잭션이 데이터에 접근하면, 처리량과 일관성은 쉽게 충돌한다. 잠금 중심의 접근에서는 읽기가 쓰기를 기다리거나 쓰기가 읽기에 막힐 수 있으며, 공유 Lock을 사용하더라도 데이터 일관성 훼손 가능성이 남는다.

MVCC(Multi Version Concurrency Control)는 이 문제를 데이터 버전으로 푼다. 읽기 작업은 자신이 시작된 시점의 스냅샷을 보고, 쓰기 작업은 새로운 버전을 만든다. 그 결과 읽기와 쓰기가 서로를 차단하지 않도록 하면서 각 트랜잭션에 일관된 데이터 뷰를 제공할 수 있다.

데이터는 변경 이력을 가진 객체가 된다

MVCC에서는 데이터를 수정할 때 기존 값을 덮어쓰는 대신 새 버전을 생성한다. 이전 버전은 바로 제거하지 않고 남겨 두며, 트랜잭션은 시작 시점에 맞는 버전을 선택해 읽는다.

이 구조에서는 다음 특성이 함께 성립한다.

  • 데이터 변경마다 새 버전이 생성된다.
  • 기존 버전은 보존된다.
  • 트랜잭션은 시작 시점의 일관된 데이터 스냅샷을 읽을 수 있다.
  • 읽기와 쓰기가 서로를 차단하지 않는다.

페이지 내부에 버전을 두는 MGA

MGA(Multi Generation Architecture)는 데이터 페이지 안에서 여러 튜플, 즉 행의 버전을 관리하는 접근이다. 튜플이 갱신되면 기존 값을 교체하지 않고 같은 페이지에 새 튜플을 추가하며, 이전 튜플에는 유효 범위를 표시한다. PostgreSQL에서 주로 사용하는 방식이다.

PostgreSQL의 MGA 구현 예:

페이지 구조: [페이지헤더] [튜플3] [튜플2] [튜플1] [새로운튜플2] [페이지테일]

튜플은 생성 트랜잭션을 나타내는 Xmin과 삭제 트랜잭션을 나타내는 Xmax를 포함해 유효 범위를 관리한다.

페이지 헤더튜플3튜플2Xmin=100Xmax=200튜플1새로운 튜플2Xmin=200Xmax=null페이지 테일

현재 데이터와 이전 버전을 분리하는 Rollback Segment

Oracle에서 사용하는 Rollback Segment 방식에서는 현재 데이터를 데이터 블록에 유지하고, 이전 버전은 별도의 롤백 세그먼트에 저장한다. 갱신이 일어나면 데이터 블록의 레코드는 새 버전으로 바뀌고 기존 버전은 롤백 세그먼트로 보관된다.

조회 시에는 쿼리의 SCN(System Change Number)과 데이터 블록의 SCN을 비교한다. 읽기 일관성이 필요하면 롤백 세그먼트의 이전 버전을 참조하고, 버퍼 캐시에는 CR(Consistent Read) 블록을 만들어 스냅샷 읽기를 보장한다.

트랜잭션2(SCN=105)롤백 세그먼트데이터 블록트랜잭션1(SCN=100)트랜잭션2(SCN=105)롤백 세그먼트데이터 블록트랜잭션1(SCN=100)다른 쿼리(SCN=95)가같은 데이터 요청시데이터 업데이트 요청이전 버전 저장새 버전으로 갱신(SCN=100)커밋데이터 읽기 요청(SCN=105)SCN 비교(105 > 100)현재 버전 반환데이터 읽기 요청(SCN=95)SCN 비교(95 < 100)이전 버전 요청이전 버전 반환(CR 블록 생성)

SCN이 읽기 시점을 결정하는 이유

Oracle과 같은 DBMS에서 SCN은 MVCC 구현의 핵심 기준점이다. 커밋이 발생할 때 트랜잭션에 할당되는 연속 증가 고유 번호로, 데이터베이스 변경의 논리적 타임스탬프 역할을 한다.

쿼리가 시작되면 현재 SCN의 스냅샷을 얻는다. 조회 결과에는 그 SCN보다 낮은 커밋된 변경만 포함되고, 더 높은 변경은 해당 쿼리에서 보이지 않는다. 이를 통해 트랜잭션 사이의 시간적 선후관계를 판단하고 읽기 일관성을 유지한다.

동시성의 이점과 버전 관리의 비용

MVCC는 일반적인 읽기 작업에 Lock이 필요하지 않아 Lock 오버헤드를 줄이고 데드락 발생 가능성을 낮춘다. 배타적 Lock이 걸린 레코드를 만나도 읽기 작업은 대기하지 않고 처리할 수 있다. 장시간 실행되는 쿼리도 시작 시점 기준의 일관된 스냅샷을 유지하며, 애플리케이션 요구에 맞춰 일관성과 동시성의 균형을 조정할 수 있다.

대신 이전 버전을 보관하는 공간이 필요하다. 데이터 페이지나 롤백 세그먼트를 효율적으로 관리해야 하며, 더 이상 필요하지 않은 버전은 정리 대상이 된다. PostgreSQL에서는 VACUUM이, Oracle에서는 롤백 세그먼트 관리가 이 운영 부담과 맞닿아 있다. 트랜잭션 ID 또는 SCN 오버플로우 대응도 필요하며, 특정 격리 수준에서는 팬텀 읽기가 여전히 발생할 수 있으므로 격리 수준 선택을 함께 검토해야 한다.

조회와 갱신이 겹치는 시스템에서의 활용

금융 거래 시스템에서는 계좌 정보 조회와 거래 처리가 동시에 일어난다. MVCC를 적용하면 잔액 갱신 중에도 읽기 작업이 차단되지 않고, 거래 보고서는 특정 시점을 기준으로 일관된 데이터를 볼 수 있다. 높은 동시 사용자 부하에서도 안정적인 성능을 유지하는 데 도움이 된다.

전자상거래 플랫폼에서는 재고 갱신과 주문 처리가 겹친다. 블랙프라이데이와 같은 대규모 프로모션 기간에도 재고 업데이트 중 제품 정보를 조회할 수 있고, 주문 프로세스가 끝날 때까지 일관된 재고 수준을 유지할 수 있다. 높은 트래픽에서도 시스템 응답성을 확보하는 데 적합하다.

데이터 웨어하우스에서는 실시간 데이터 로드와 비즈니스 인텔리전스 쿼리가 함께 수행된다. MVCC는 데이터 로드 중에도 분석 쿼리를 실행하게 하며, 장시간 실행되는 쿼리에 일관된 데이터셋을 제공한다. ETL 프로세스와 분석 작업이 서로 간섭하는 범위도 줄일 수 있다.

MVCC데이터베이스동시성 제어트랜잭션읽기 일관성