[데이터베이스] 트랜잭션 격리 수준(Isolation level)

서유진·2022년 9월 24일
2

기술이 술술

목록 보기
3/5
post-thumbnail

트랜잭션 격리 수준(Isolation level)

트랜잭션의 특징 ACID 중 Isolation에 따라, 트랜잭션간에 격리성(독립성)을 완전히 보장해야 합니다. 하지만 그럴 경우를 완전히 보장하기 위해서는 모든 트랜잭션을 차례로 처리 해야 하고, 이는 성능의 하락으로 이어집니다.

트랜잭션 격리 수준은, 동시에 여러 트랜잭션이 처리될 때 특정 트랜잭션이 다른 트랜잭션에서 변경하거나 조회하는 데이터를 볼 수 있도록 허용할지 말지를 결정하는 것입니다.

0 : READ UNCOMMITTED (커밋되지 않은 읽기)

  • 각 트랜잭션에서의 변경 내용이 COMMIT이나 ROLLBACK 여부에 상관 없이 다른 트랜잭션에서 값을 읽을 수 있습니다.
  • 정합성에 문제가 많은 격리 수준이기 때문에 사용하지 않는 것을 권장합니다.
  • DIRTY READ 발생

    DIRTY READ
    트랜잭션이 작업이 완료되지 않았는데도 다른 트랜잭션에서 볼 수 있게 되는 현상
    💡 예시
    트랜잭션 A 가 실행되고 update 됐을 때 그 사이에 트랜잭션 B가 실행된다.
    그러면 트랜잭션 A에서 커밋이 되지 않았음에도 불구하고, 트랜잭션 B에서 트랜잭션 A가 update한 내용을 확인할 수 있게 된다.

1 : READ COMMITTED (커밋된 읽기)

  • COMMIT 이 된 데이터만 읽습니다.

  • RDB에서 대부분 기본적으로 사용되고 있는 격리 수준

  • Dirty Read와 같은 현상은 발생하지 않지만 NON-REPEATABLE READ 발생

    NON-REPEATABLE READ
    하나의 트랜잭션 내에서 동일한 SELECT 쿼리를 실행했을 때 항상 같은 결과를 보장해야 한다는 REPEATABLE READ 정합성에 어긋나는 것
    💡 예시
    트랜잭션 A에서 update 된 내용이 타 트랜잭션에서 바로 보여지지는 않는다. 근데 트랜잭션 A에서 커밋이 완료되었는데 트랜잭션 B에는 아직 완료되지 않은 경우, 트랜잭션 B에서 다시 한번 조회를 하게 된다면 update 된 상태가 조회가 된다
    같은 조회(셀렉트)문인데도 결과가 다르기 때문에 정합성에 어긋난다.

  • 실제 테이블 값을 가져오는 것이 아니라 Undo 영역에 백업된 레코드에서 값을 가져온다.

    UNDO 영역: 
    간단하게 데이터를 저장하는 버퍼 기능을 한다고 보면 되고, 트랜잭션에서 연산(커밋 롤백)이 이루어지지 않아도 질의문에 의해 수정이 생기면 수정되기 이전 값이 저장되는 영역

2 : REPEATABLE READ (반복 가능한 읽기)

  • 자신의 트랜잭션이 생성되기 이전의 트랜잭션에서 COMMIT 이 된 데이터만 읽습니다.
  • MySQL과 MariaDB 가 기본으로 사용하는 격리 수준
  • MySQL에서는 트랜잭션마다 트랜잭션 ID를 부여하여 트랜잭션 ID보다 작은 트랜잭션 번호에서 변경한 것만 읽게 된다.

    PHANTOM READ
    다른 트랜잭션에서 수행한 변경 작업에 의해 레코드가 보였다가 안 보였다가 하는 현상
    💡 예시
    같은 테이블에 접근하는 여러개의 트랜잭션을 처리하고 있습니다. 그중 한 트랜잭션이 SELETE ~~ FOR UPDATE 을 사용하여 쓰기 잠금을 걸고 싶다고 가정합니다. 쿼리문에 따라, SELECT하려는 레코드에 쓰기 잠금을 걸어야 하는데, Undo 레코드에는 잠금을 걸 수 없습니다. 따라서 위와 같은 쿼리는 Undo 영역의 변경 전 데이터를 가져오는 것이 아니라 현재 레코드의 값을 가져오게 됩니다! 따라서 레코드가 보였다 안보였다 한다고 해서 🎭 PHANTOM 이라고 합니다.

REPEATABLE READ 추가 설명
모든 트랜젝션은 번호를 갖고, undo영역에서는 트랜잭션 번호를 함께 보관합니다.
아까와 같이 트랜잭션 A트랜잭션 B가 있습니다. 트랜잭션 A의 번호는 13번이고 트랜잭션 B의 번호는 10번입니다.
트랜잭션 B가 시작했습니다.
트랜잭션 A에서는 일부 값을 업데이트 하고 커밋하였습니다.
트랜잭션 B 안에서 실행되는 모든 SELECT 쿼리는 자신의 트랜잭션인 10번 보다 작은 트랜잭션 번호에서 변경한 것만 보게 됩니다. 즉, 번호가 13인 트랜잭션 A에서 변경한 내용은 10번인 트랜잭션 B에 영향을 주지 않습니다. 이는 Undo 영역에 트랜잭션 번호가 저장되어있기 때문에 가능한 것입니다.

3 : SERIALIZABLE (직렬화 가능)

  • 가장 단순한 격리 수준이지만 가장 엄격한 격리 수준
  • 데이터를 접근할 때, 항상 Lock을 걸고 데이터를 조회
  • SERIALIZABLE에서는 PHANTOM READ가 발생하지 않는다.
  • 성능 문제로 데이터베이스에서 거의 사용되지 않는다.

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

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


사진 출처
격리 수준이 높아지면서 데이터의 일관성이 유지될 수 있지만, 동시에 처리가능한 트랜잭션의 양은 떨어집니다. 격리수준이 낮아지면 일관성은 유지되기 어렵지만, 동시에 처리할 수 있는 트랜잭션의 양은 늘어나게 됩니다.

  • 동시성 : 동시에 수행하는 트랜잭션 양
  • 일관성 : 트랜잭션의 작업 처리 결과가 항상 일관성이 있어야 한다는 것
profile
Backend Dev.

0개의 댓글