Database Transaction Isolation Level

2SEONGA·2025년 3월 11일
0

DB

목록 보기
4/5
post-thumbnail

ACID 중 (Guaranteed) Consistency 즉, Data Integrity 데이터 무결성을 위해 트랜잭션을 도입했는데
트랜잭션의 궁극적인 목표는 모든 Operation 의 독립성을 보장하는 것이나, 독립성의 과도한 보장은 성능의 저하 유발

  • 왜 의도적으로 Transaction 간 격리 정도를 느슨하게하나?
    • 동시성 단일 시간 내 많은 “읽기” Transaction 처리 위해
      (각 격리 레벨 모두 Read 를 이름에 보유)
    • 각 레벨(L0 ~ L3) 별 DB 표준 에러(SQL Standard Error)와 그걸 방지하기위한 다음 레벨의 방책들
  • 격리 레벨은 Transaction 간 격리 정도에 따라
    느슨한 것에서부터 → 타이트한 직렬화 수준까지 정의

1. L0 : Read Uncommitted ← Dirty Read

  • 커밋되지 않은 데이터 변경 사항 read 가능 : ROLLBACK, COMMIT 여부에 상관 없이 모든 값
  • 가장 빠르기 때문에 데이터 일관성 혹은 정합성(Consistancy)이 조금 떨어지더라도 성능을 극대화 시 사용
  • Dirty Read
    : 한 트랜잭션에서 타 트랜잭션에서 커밋하지 않은 데이터 변경 사항을 read
    • read 가 매우 빈번하지만 굳이 데이터 정합성이 별로 필요없는 어플리케이션에 적합

[ 사진 출처 : 트랜잭션의 격리 수준(isolation Level)이란? ]


2. L1 : Read Committed ← Non-Repeatable Read

각 데이터베이스 별 MVCC 지원 방식이 상이하나,
이 글에서는 MySQLUndo 영역을 통한 MVCC 지원 예로 격리 수준을 설명할 것

L1 : Read Committed 에서부터 MVCC 가 활용

  • UPDATE 로 값을 수정할 때는 Undo 영역이 아닌 실제 레코드를 변경
    • Undo 영역에 백업된 데이터는 불필요해진 순간에 주기적으로 Garbage Collection
    • Undo 영역에 백업된 데이터가 많이 쌓인다면 DBMS 서버 성능 저하 가능성 존재
  • 이러한 변경 방식이 MVCC(Multiversion Concurrency Control)
    • MySQL(InnoDB)Undo 영역으로 MVCC 지원
      • InnoDB 엔진은 일단 실행된 모든 쿼리를 DB (실제 레코드) 에 적용, Commit 되지 않았어도
      • Consistent Read
        : 현재 DB (실제 레코드) 가 아닌 Undo 영역의 Snapshot 을 읽는 것
        • PostgresQLSnapshot(First-Committer Win)으로 MVCC 지원
        • MySQL 과 거의 동일하게 동작하나 DELETE, INSERT 에 미적용 등 다른 점들이 존재
  • 다른 트랜잭션에 commit 된 변경 사항만 read 가능
    : 실제 테이블 값이 아닌 Undo 영역에 백업된 값을 read
    • 매 read 마다 + 실제 테이블 값이 아닌 Undo 영역에 백업된 값 read
      = Consistent Read
      • 다른 표현으로는 Consistent Non-locking Read
  • 가장 많이 사용되는 격리 수준으로, commit 되지 않은 정보는 read 불가
  • Non-Repeatable Read
    : 한 트랜잭션 내 반복해서 read 할 때, 타 트랜잭션의 시작과 끝의 다른 값을 read
    • 이 때문에 입출금이 빈번한 금전적 처리와 같이,
      read 가 빈번한 어플리케이션에는 부적합

[ 사진 출처 : 트랜잭션의 격리 수준(isolation Level)이란? ]


3. L2 : Repeatable Read ← Phantom Read

각 데이터베이스 별 MVCC 지원 방식이 상이하나,
이 글에서는 MySQLUndo 영역을 통한 MVCC 지원 예로 격리 수준을 설명할 것

  • 같은 데이터 필드는 여러 번 반복해서 읽더라도 동일한 값 : 버져닝 기반으로 Undo 영역에 백업된 값만 read
    • 첫 Read 시점 기준으로 + 실제 테이블 값이 아닌 Undo 영역에 백업된 값을 read = Consistent Read
      • 다른 표현으로는 Consistent Non-locking Read
  • 한 트랜잭션이 특정 값을 read 하는 도중에, 타 트랜잭션이 값을 뒤늦게 수정하더라도 이전 버전의 백업된 값을 read
    • 일반적으론 새로운 row 를 추가하거나 기존 row 를 삭제해도 MVCC 버져닝 덕분에 Phantom Read 미발생
      • 현재 트랜잭션과 다른 타 트랜잭션 버전이 무엇을 하던 어차피 버전 기반으로 무시하기 때문
      • MySQL, PostgresQL 등 MVCC 를 지원하는 모든 DBMS 에서 사실상 Phantom Read 미발생
    • 단, read 잠금(Exclusive Lock)을 거는 경우엔 (하지만 거의 이런 경우는 미존재)
      • 일반 DBMS 는 Record Lock 이라 Phantom Read 발생
        • Record Lock = 쉬운 이해를 위해서 Row Lock 이라고 생각
          • Row 에 대한 UPDATE 방지 O
          • Table 에 대한 INSERT, DELETE 방지 X
            Phantom Read(INSERT, DELETE) 발생
      • MySQL 은 Gap Lock 을 쓰기때문에 Phantom Read 미발생
        • Gap Lock = 쉬운 이해를 위해서 Rows Lock 이라고 이해
          • Rows 에 대한 INSERT, DELETE 방지 O
          • Table 에 대한 INSERT, DELETE 방지 X
            • 하지만 일부의 Rows 에서는 Phantom Read 미발생한다는 의미
        • 실제로는 Index Record 에 대한 Lock
  • Phantom Read
    : UPDATE(Row) 가 아닌 INSERT 혹은 DELETE 에 대해선 Lock 이 걸려있지 않아 발생
    • 우리 어제 진짜 재미있었지? / 맞아! 넷이서 노니까 진짜 재밌었어 / 어? 우리 세명..이었어..

[ 사진 출처 : 트랜잭션의 격리 수준(isolation Level)이란? ]


4. L3 : Serializable

  • 완전한 ACID를 보장하는 격리 수준
  • 보통 해당 트랜잭션에 관련된 모든 테이블을 잠그기 때문에 성능이 가장 비효율적인 격리 수준
    • SELECT 만 해도 트랜잭션이 완료될 때까지 SELECT 문장이 사용하는 모든 데이터에 Shared Lock
    • Shared Lock : read 는 허용하나 수정, 삽입, 삭제 모두 허용하지 않겠다는 것
      • 참고 : SELECT 가 아닌 트랜잭션이 수정, 삽입, 삭제 시 Exclusive Lock 적용


5. Spring Data JPA 에서 @Transactional 옵션 중 Isolation Level

Spring (Boot) 개발 시 Spring Data JPA 으로 개발할때 클래스나 메서드마다 @Transactional 세부 설정 가능


profile
(와.. 정말 Chill하다..)

0개의 댓글