트랜잭션 격리수준의 이해

슈퍼대디·2024년 12월 23일

CS면접대비

목록 보기
6/13

데이터베이스 트랜잭션 격리수준의 이해

목차

  1. 트랜잭션 기본 개념
  2. 트랜잭션 격리수준의 필요성
  3. 트랜잭션 격리수준과 문제점
  4. DBMS별 특징
  5. 면접 예상 질문

1. 트랜잭션 기본 개념

ACID 속성

트랜잭션은 데이터베이스의 데이터를 다루는 논리적인 작업의 단위이며, 다음과 같은 ACID 속성을 보장해야 합니다:

  1. 원자성 (Atomicity)

    • 트랜잭션의 모든 연산이 완전히 수행되거나, 전혀 수행되지 않아야 함
    • 중간 상태가 존재하지 않음
  2. 일관성 (Consistency)

    • 트랜잭션 실행 전과 후의 데이터베이스가 일관된 상태를 유지
    • 무결성 제약조건이 항상 만족되어야 함
  3. 격리성 (Isolation)

    • 동시에 실행되는 트랜잭션들이 서로 영향을 미치지 않음
    • 격리수준에 따라 보장 정도가 다름
  4. 지속성 (Durability)

    • 성공적으로 완료된 트랜잭션의 결과는 영구적으로 보장
    • 시스템 장애가 발생하더라도 데이터는 보존

2. 트랜잭션 격리수준의 필요성

동시성 제어의 필요성

여러 트랜잭션이 동시에 수행될 때 발생할 수 있는 문제들:

  1. Dirty Read

    • 다른 트랜잭션에 의해 수정되었지만 아직 커밋되지 않은 데이터를 읽는 현상
    • 데이터 정합성에 심각한 문제 발생 가능
  2. Non-Repeatable Read

    • 한 트랜잭션 내에서 같은 데이터를 두 번 읽었을 때 결과가 다른 현상
    • 다른 트랜잭션의 수정으로 인해 발생
  3. Phantom Read

    • 한 트랜잭션 내에서 같은 쿼리를 두 번 실행했을 때 결과 집합이 다른 현상
    • 다른 트랜잭션의 삽입/삭제로 인해 발생

3. 트랜잭션 격리수준 상세

READ UNCOMMITTED (Level 0)

가장 낮은 격리수준으로, 다른 트랜잭션의 변경사항이 COMMIT이나 ROLLBACK 여부와 관계없이 보여집니다.

예시 상황: 은행 계좌 조회

초기상태: 계좌잔액 1000원

[Transaction 1]                    [Transaction 2]
계좌잔액 갱신 (-500원)
잔액 = 500원
                                  잔액 조회
                                  -> 500원 확인 (Dirty Read 발생)
ROLLBACK
잔액 = 1000원
                                  잔액 사용 시도 실패

특징

  • Dirty Read 발생: 아직 커밋되지 않은 데이터를 다른 트랜잭션에서 읽을 수 있음
  • 데이터 정합성을 전혀 보장하지 않음
  • 실무에서는 거의 사용되지 않음

READ COMMITTED (Level 1)

커밋된 데이터만 읽을 수 있는 격리수준입니다. Oracle의 기본 격리수준입니다.

예시 상황: 상품 재고 확인

초기상태: 상품 A의 재고 100개

[Transaction 1]                    [Transaction 2]
재고 조회
-> 100개 확인
                                  재고 수정 (-30개)
                                  재고 = 70개
                                  COMMIT
재고 다시 조회
-> 70개 확인 (Non-Repeatable Read 발생)

특징

  • Dirty Read 방지: 커밋된 데이터만 읽기 가능
  • Non-Repeatable Read 발생: 같은 트랜잭션 내에서 같은 데이터를 두 번 읽었을 때 결과가 다를 수 있음
  • 일반적인 웹 애플리케이션에서 가장 많이 사용됨

REPEATABLE READ (Level 2)

MySQL InnoDB의 기본 격리수준으로, 트랜잭션이 시작된 시점의 데이터를 일관되게 보장합니다.

예시 상황: 회원 목록 조회

초기상태: 회원 테이블에 10명의 회원 존재

[Transaction 1]                    [Transaction 2]
전체 회원 조회
-> 10명 확인
                                  새 회원 추가
                                  COMMIT
전체 회원 수 조회
-> 10명 유지 (이전 스냅샷 유지)
특정 조건으로 회원 조회
-> 11명 확인 (Phantom Read 발생 가능)

특징

  • Non-Repeatable Read 방지: 트랜잭션 시작 시점의 데이터 일관성 보장
  • Phantom Read는 특정 상황에서 발생 가능
    • MySQL InnoDB는 넥스트 키 락으로 이를 방지
  • MVCC를 통한 구현으로 높은 동시성 제공

SERIALIZABLE (Level 3)

가장 높은 격리수준으로, 완벽한 데이터 정합성을 보장합니다.

예시 상황: 동시 주문 처리

초기상태: 상품 B의 재고 1개

[Transaction 1]                    [Transaction 2]
상품 B 재고 확인
-> 1개 확인
                                  상품 B 재고 확인
                                  -> 대기 (잠금)
주문 처리
재고 차감
COMMIT
                                  -> 0개 확인 (일관성 보장)

특징

  • 모든 데이터 일관성 문제 방지
  • 트랜잭션의 완벽한 격리 보장
  • 성능 이슈로 실무에서는 거의 사용되지 않음
  • 읽기 작업에도 잠금이 설정됨

4. DBMS별 특징

MySQL (InnoDB)

  • 기본 격리수준: REPEATABLE READ
  • REPEATABLE READ에서도 PHANTOM READ가 발생하지 않도록 넥스트 키 락(Next-Key Lock) 사용
  • 갭 락(Gap Lock)을 통한 팬텀 리드 방지

Oracle

  • 기본 격리수준: READ COMMITTED
  • SERIALIZABLE 구현 시 낙관적 락(Optimistic Locking) 사용
  • MVCC를 통한 읽기 일관성 제공

PostgreSQL

  • 기본 격리수준: READ COMMITTED
  • SERIALIZABLE 격리수준에서 SSI(Serializable Snapshot Isolation) 제공
  • MVCC를 통한 동시성 제어

5. 면접 예상 질문

Q: 트랜잭션 격리수준이란 무엇이며, 각 격리수준의 차이를 설명해주세요.
A: 트랜잭션 격리수준은 동시에 실행되는 트랜잭션들이 서로에게 영향을 미치는 정도를 제어하는 기준입니다. READ UNCOMMITTED는 커밋되지 않은 데이터도 읽을 수 있어 데이터 정합성이 매우 낮고, READ COMMITTED는 커밋된 데이터만 읽을 수 있어 더티 리드는 방지됩니다. REPEATABLE READ는 트랜잭션 시작 시점의 데이터 일관성을 보장하며, SERIALIZABLE은 완벽한 격리를 제공하지만 성능이 가장 낮습니다. 각 수준은 높아질수록 더 강력한 데이터 일관성을 제공하는 대신 동시성 처리 성능이 저하됩니다.

Q: Dirty Read, Non-Repeatable Read, Phantom Read의 차이점을 설명해주세요.
A: 이 세 가지는 트랜잭션 격리수준에 따라 발생할 수 있는 데이터 불일치 현상입니다. Dirty Read는 아직 커밋되지 않은 변경사항을 다른 트랜잭션에서 읽을 수 있는 현상입니다. Non-Repeatable Read는 한 트랜잭션 내에서 같은 데이터를 두 번 읽었을 때 결과가 다른 현상으로, 다른 트랜잭션의 커밋된 수정으로 인해 발생합니다. Phantom Read는 한 트랜잭션에서 같은 쿼리를 두 번 실행했을 때 결과 집합이 달라지는 현상으로, 다른 트랜잭션의 삽입이나 삭제로 인해 발생합니다.

Q: 실무에서는 주로 어떤 격리수준을 사용하나요? 그 이유는 무엇인가요?
A: 실무에서는 주로 READ COMMITTED나 REPEATABLE READ 격리수준을 사용합니다. READ UNCOMMITTED는 데이터 정합성을 보장할 수 없어 위험하고, SERIALIZABLE은 동시성 처리 성능이 매우 낮아 실무에 적합하지 않습니다. Oracle은 기본적으로 READ COMMITTED를, MySQL(InnoDB)은 REPEATABLE READ를 사용하며, 이는 데이터 정합성과 성능 사이의 적절한 균형을 제공합니다. 특히 READ COMMITTED는 커밋된 데이터만 읽을 수 있어 기본적인 데이터 정합성을 보장하면서도 적절한 동시성 처리 성능을 제공하기 때문에 많이 사용됩니다.

참고 자료

profile
성장하고싶은 Backend 개발자

0개의 댓글