트랜잭션 격리수준

JANG SEONG SU·6일 전
0

데이터 베이스

목록 보기
4/4
post-thumbnail

0 : READ UNCOMMITTED

  • 다른 트랜잭션이 커밋되지 않은 데이터를 읽을 수 있음

발생할 수 있는 문제

  • Dirty Read: 아직 커밋되지 않은 데이터를 읽는 것
  • Non-Repeatable Read: 한 트랜잭션에서 2번 이상의 쿼리를 조회했을 때, 그 결과가 다른 것을 의미 (다른 트랜잭션에서 Update Delete 했을 때 발생)
  • Phantom Read: 한 트랜잭션에서 2번 이상 조회했을 때, 없던 데이터가 나타나는 경우 (다른 트랜잭션에서 Insert 했을 때 발생)

🚀 언제 사용하면 좋을까?

  • 데이터 정합성이 약간 깨져도 성능이 중요한 경우(e.g., 대용량 데이터 배치 처리).

1 : READ COMMITTED

  • 가장 최신으로 commit 된 데이터만 읽을 수 있음

발생할 수 있는 문제

  • Non-Repeatable Read: 한 트랜잭션에서 2번 이상의 쿼리를 조회했을 때, 그 결과가 다른 것을 의미 (다른 트랜잭션에서 Update Delete 했을 때 발생)
  • Phantom Read: 한 트랜잭션에서 2번 이상 조회했을 때, 없던 데이터가 나타나는 경우 (다른 트랜잭션에서 Insert 했을 때 발생)

🚀 언제 사용하면 좋을까?

사용자가 글을 조회할 때, 다른 사용자가 댓글을 다는 중이라도 최신 상태를 확인할 수 있어야 함

2 : REPEATABLE READ

  • 같은 트랜잭션 내에서 동일한 데이터를 여러 번 조회할 경우, 항상 같은 값이 보이도록 보장

발생할 수 있는 문제

  • Phantom Read: 한 트랜잭션에서 2번 이상 조회했을 때, 없던 데이터가 나타나는 경우 (다른 트랜잭션에서 Insert 했을 때 발생)

궁금했던 내용

내가 궁금했던 내용은 REPEATABLE READ 수준에서는 어떤한 이유로 UPDATE에 대해서는 데이터의 정합성이 보장되고, 또 INSERT에 대해서는 정합성이 보장이 안되는지 궁금했다.

기본적으로 REPEATABLE READ 격리 수준에서 MVCC(Multi-Version Concurrency Control) 방식으로 트랜잭션이 시작될 때 특정 시점의 데이터를 읽도록 하기 때문이다.

MVCC가 동작하는 방식
1. 트랜잭션이 시작될 때, 그 시점에 undo 로그 기반으로 커밋된 데이터의 버전 스냅샷을 생성.
2. 이후 트랜잭션이 계속 진행되는 동안 이 스냅샷을 유지.
3. 다른 트랜잭션에서 UPDATEDELETE를 수행하고 COMMIT하더라도, 현재 트랜잭션에서는 초기 스냅샷의 데이터를 계속 유지하여 동일한 결과를 보장함.

그럼 왜 INSERT된 데이터(팬텀 레코드)는 MVCC로 차단되지 않는가?

  • MVCC는 기존 행을 추적할 뿐, 새로운 행을 관리하지 않음
  • REPEATABLE READ는 트랜잭션이 시작될 때 현재 존재하는 데이터의 특정 버전을 유지함.
  • 하지만, 새로운 행(INSERT)이 추가될 경우, 이는 기존 버전 관리 대상이 아니므로 MVCC 스냅샷을 통해 차단할 수 없음.
  • 즉, INSERT된 데이터는 기존 스냅샷과 무관하게 물리적인 디스크 또는 인덱스에서 조회될 수 있음.

MySQL InnoDB에서 Gap Lock 사용으로 Phantom Read 방지

  • SELECT ... FOR UPDATE 또는 SELECT ... LOCK IN SHARE MODE를 사용하여 해당 범위 내에서 새로운 INSERT가 차단되도록 함.

  • Gap Lock은 기존 행과 행 사이의 "공백(Gap)"에도 락을 걸어 새로운 행이 추가되지 못하도록 하는 방식임.

  • 단점: GAP Lock은 데드락이 걸릴 수 있음

  • 데드락 예시

    ✅ Deadlock 발생 예제
    -- 트랜잭션 1 (A)
    BEGIN;
    SELECT * FROM employees WHERE salary BETWEEN 3000 AND 5000 FOR UPDATE;
    sql
    복사
    편집
    -- 트랜잭션 2 (B)
    BEGIN;
    SELECT * FROM employees WHERE salary BETWEEN 4000 AND 6000 FOR UPDATE;
    -- 🚨 트랜잭션 1이 완료될 때까지 대기
    

🚀 언제 사용하면 좋을까?

은행 송금 시스템

  • A 계좌에서 B 계좌로 송금할 때, 송금 전후로 잔액이 변하지 않아야 함
  • 예) A가 송금 시 잔액을 확인하고, 돈을 보낼 때 그 잔액이 바뀌면 오류 발생 가능 → 같은 값 유지 필요
  • 즉 데이터 수정에 대한 정합성을 보장할때

3 : SERIALIZABLE

  • 가장 높은 격리 수준. 모든 트랜잭션을 직렬적으로 실행.
  • Dirty Read, Non-Repeatable Read, Phantom Read가 모두 방지됨.
  • 성능 문제로 데이터베이스에서 거의 사용되지 않는다.

궁금했던 내용

이때 내가 궁금한 점은 SERIALIZABLE에서는 모든 트랜잭션이 직렬적으로 실행된다면, "왜 Shared Lock이 필요할까?" 라는 것이다
SERIALIZABLE 격리 수준이 "모든 트랜잭션을 직렬적으로 실행"하는 것과 같다고 오해하기 쉽지만,실제로는 DBMS가 직렬화된 순서를 보장하는 방식이지, 물리적으로 한 트랜잭션씩 실행하는 것은 아니다
Shared Lock을 적용하여, 다른 트랜잭션에서 INSERT, UPDATE, DELETE가 차단되므로 직렬화 효과가 발생하는 것이다

🚀 언제 사용하면 좋을까?

항공사 좌석 예약 시스템

  • 여러 사용자가 동일한 좌석을 예약하려고 할 때, 동시에 접근하지 못하게 완전히 차단
  • 예) 동일한 좌석이 두 명에게 배정되는 문제 방지
  • 즉, 데이터 자체의 정합성을 보장할 때.

트랜잭션 문제들 한눈에 정리

트랜잭션 격리 수준에 따른 동시성과 일관성 변화

격리 수준이 높아지면서 데이터의 일관성이 유지될 수 있지만, 동시에 처리가능한 트랜잭션의 양은 떨어집니다. 격리수준이 낮아지면 일관성은 유지되기 어렵지만, 동시에 처리할 수 있는 트랜잭션의 양은 늘어나게 됩니다.
  • 동시성 : 동시에 수행하는 트랜잭션 양
  • 일관성 : 트랜잭션의 작업 처리 결과가 항상 일관성이 있어야 한다는 것
profile
Software Developer Lv.0

0개의 댓글

관련 채용 정보