변수의 기록

(데이터베이스) MVCC와 Isolation Level – Oracle 예제 본문

CS지식/데이터베이스 (Database)

(데이터베이스) MVCC와 Isolation Level – Oracle 예제

불광동 물주먹 2025. 5. 21. 00:39

MVCC와 Isolation Level – Oracle 예제

1. MVCC란?

**MVCC (다중 버전 동시성 제어)**는 동시성을 높이기 위해 트랜잭션마다 **자신만의 일관된 데이터 시점(snapshot)**을 제공하는 방식이다.
MVCC를 사용하는 데이터베이스는 읽기와 쓰기 간의 충돌(Blocking)을 제거하고, 성능과 일관성을 동시에 추구한다.


2. MVCC의 핵심 개념

 

구분 설명
읽기(read) 특정 트랜잭션이 시작될 때의 "시점" 기준으로 commit된 데이터만 읽는다
쓰기(write) 기존 데이터를 직접 수정하지 않고, 새로운 버전의 데이터를 생성
커밋 후 노출 다른 트랜잭션은 오직 commit된 버전만 읽을 수 있다
비차단 (non-blocking) 읽기와 쓰기 작업은 서로 Lock을 걸지 않음
 

3. MVCC와 Isolation Level

각 격리 수준(Isolation Level)에 따라 **"읽기 시점"**과 MVCC의 버전 선택 방식이 달라진다.

(1) Read Uncommitted

  • MVCC가 아닌 Lock 기반에서나 사용됨.
  • MVCC를 사용하는 DB에서는 의미가 없음 (항상 커밋된 데이터만 보기 때문).
  • Oracle은 이 레벨을 지원하지 않음.

(2) Read Committed (기본 격리 수준 in Oracle)

  • "읽기 순간" 기준으로 커밋된 데이터를 읽는다.
  • 하나의 트랜잭션 내에서 같은 쿼리를 두 번 실행해도 다른 결과가 나올 수 있다.
  • Oracle에서는 SELECT할 때마다 최신 커밋된 버전을 다시 조회한다.
-- Session A
BEGIN;
UPDATE products SET price = 200 WHERE id = 1;

-- Session B
SELECT price FROM products WHERE id = 1; -- 100 (기존값)

-- Session A
COMMIT;

-- Session B
SELECT price FROM products WHERE id = 1; -- 200 (변경 반영됨)

(3) Repeatable Read

  • 트랜잭션이 시작된 시점의 커밋된 데이터를 계속 유지.
  • 같은 쿼리를 반복해도 일관된 결과.
  • Oracle에서는 Serializable로 통합 처리됨 (정확히는 snapshot 기반 직렬화).

(4) Serializable (in Oracle)

  • 트랜잭션 간 충돌을 방지하기 위해 충돌 탐지 후 오류 발생.
  • Oracle은 MVCC를 활용하여 Serializable 격리 수준에서도 Lock을 사용하지 않음.
  • 읽기 시점에 없는 데이터에 대해 다른 트랜잭션이 insert/update하면, 충돌이 발생해 ORA-08177 오류를 던짐.
-- Session A
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SELECT * FROM orders WHERE id = 10;

-- Session B
INSERT INTO orders (id, ...) VALUES (10, ...);
COMMIT;

-- Session A
-- 다시 같은 조건으로 insert 시도 시 ORA-08177
INSERT INTO orders (id, ...) VALUES (10, ...);  -- 실패

4. MVCC와 Recoverability

  • MVCC는 commit된 데이터만 읽기 때문에, 자연스럽게 non-repeatable read, dirty read 방지
  • 하지만 **"write-write conflict"**는 막지 못한다 → 예: Lost Update

예시: Lost Update

 
-- Session A
SELECT qty FROM stock WHERE id = 1; -- 10
-- Session B
SELECT qty FROM stock WHERE id = 1; -- 10

-- Session A
UPDATE stock SET qty = 9 WHERE id = 1;

-- Session B
UPDATE stock SET qty = 8 WHERE id = 1;

5. Lost Update 방지를 위한 전략

  • MVCC 환경에서 Repeatable Read 수준이라도 lost update는 발생할 수 있다.
  • 이를 막기 위해서는 명시적인 버전 체크 혹은 충돌 탐지(commit 시점에) 필요

Oracle에서 해결법

  1. Optimistic Locking (애플리케이션 단 버전 필드 사용)
  2. Serializable 격리 수준 사용
    → insert/update 충돌 발생 시 ORA-08177 발생

6. 관련 심화 개념

 

개념 설명
Undo Segment MVCC의 과거 버전을 보존하기 위한 영역. 오래된 쿼리 또는 Rollback 시 필요
Read Consistency 트랜잭션이 항상 동일한 시점의 데이터를 읽을 수 있도록 보장
Snapshot 트랜잭션이 시작할 때의 커밋된 데이터 상태
First-updater-wins 동일 데이터에 대해 먼저 update한 트랜잭션이 우선권을 갖는 전략 (MySQL의 InnoDB)
 

7. Oracle vs 다른 DB의 MVCC 차이


DBMS MVCC 방식 특징
Oracle Undo Segment 기반 읽기 일관성 제공, 모든 격리 수준에서 MVCC 적용
PostgreSQL Tuple 버전 유지 Vacuum 필요, Snapshot을 쿼리 전체에 고정
MySQL (InnoDB) Row-based version repeatable read에서 phantom read 방지 안됨 (gap lock 보완 필요)
 

정리 요약

  • MVCC는 Lock 없이 동시성을 제공
  • Read는 시점 기준으로 과거 버전 조회
  • Write는 새 버전 생성 → Undo에 과거 기록 저장
  • 격리 수준에 따라 “읽기 시점”이 달라진다
  • Oracle은 Read Committed, Serializable에 MVCC 적용
  • 충돌 방지를 위해 Serializable, Optimistic Locking, 버전 필드 등을 고려해야 한다