DB 트랜잭션 - 격리수준(Transaction Isolation Level)

    트랜잭션

    DB에서의 트랜잭션이란, 보통 데이터베이스의 어떤 변경을 유발하는 작업 단위를 의미한다. 논리적으로 한 개의 실행 단위를 뜻하며, 물리적으로는 한 개 혹은 여러 개의 실행단위가 묶여 실행되기도 한다. 설명의 편의성을 위해, 종종 은행 계좌간 돈을 이체하는 사례가 주로 인용된다.

     

    트랜잭션의 특징 - ACID

    DB에서의 트랜잭션은 아래 네 개의 특징을 지닌다.

    • Atomicity
    • Consitency
    • Isolation
    • Durability

     

    Atomicity(원자성)

    트랜잭션은 논리적으로 하나의 실행단위여야 한다. 물리적으로 여러 개의 statement로 구성되어 있다 하더라도 논리적인 단위로 묶일 수 있어야 한다. 하나의 실행단위라면, 실행시 두 개의 상태로 귀결된다. 성공하거나 실패하거나 (all or nothing). 즉, 여러 개의 statement로 작성되었더라도 트랜잭션으로 묶인다면, 전체 문장이 성공하거나 전체 문장이 실패하는 것으로 되어야 한다. (부분 성공/ 부분 실패 없음)

     

    Consitency(일관성)

    데이터베이스의 일관성 있는 데이터 상태로 변환되는 것을 보장해야 한다. 어떤 변경은, 반드시 허용된 방식으로만 이뤄져야 한다. 데이터는 시스템이 정의한 형식/룰 등을 위반하지 않아야 한다.

     

    Isolation(격리성, 독립성)

    서로 다른 트랜잭션은 서로에게 독립적이어야 한다. (서로에게 간섭하지 않아야 한다.) 결국, 동시성에 대한 요구사항이다.

     

    Durability(지속성, 영속성)

    일단 성공적으로 실행/반영된(commit) 내용은 시스템 장애가 나더라도 데이터가 영속적으로 저장되는 것이 보장되어야 한다.

     

     

    Transaction Isolation Level - 왜 여러 단계가 있나?

    제목으로도 예상할 수 있겠지만 트랜잭션 격리성/동시성에 어떤 제어수준이 있다는 것을 뜻한다. 그런데, 독립/격리하면 됐지 왜 단계가 필요할까? 결국 무엇인가를 서로 트레이드 오프한다는 것이다. 자동차로 비유하자면, 1-4단계의 기어가 있는 셈인데, 천천히 달릴 수록 안전하고 고속으로 달릴 수록 안전 대신 속도를 더 높이는 것과 유사하다고 생각해 보자.

    트랜잭션 격리/독립 레벨이라고 하면, 한 번에 잘 와닿지도 않고 오래 기억하기도 쉽지 않다. 차라리, "트랜잭션 동시성 지원 수준"이라고 기억하는 것이 더 효과가 좋을 것 같다. 이렇게 용어를 바꿔놓으면, 동시성 지원을 위해 트랜잭션을 얼마나 엄격하게 혹은 느슨하게 관리하느냐의 지원 수준에 대한 이야기라고 볼 수 있겠다. 그리고, 제어를 통해 얻고자 하는 것은 결국 성능과 관련이 있다.

    이는 공교롭게도 사람들의 시스템과 비슷하다. 규제를 강화하면 문제를 일으킬 가능성(물론 반대급부도 있지만)이 줄어드는 대신 일처리가 느려진다. 규제를 완화하면 문제가 발생해도 일처리가 빨라진다. 그리고, DB에서는 이 때 발생할 수 있는 문제들을 사전에 정의해 두었다. 즉, 아는 문제로 떠안고 가는 것이고, 특징을 잘 인지하고 쓰면 된다고 본다.

     

    Transaction Isolation Level에 따라 발생할 수 있는 문제

    표준에 언급된 대표적인 문제들로 다음의 세 가지가 있다.

    dirty reads

    • A 트랜잭션이, B 트랜잭션의 수정 후 commit되기도 전 상태의 데이터를 읽을 수 있을 때 발생한다.
    • 연관된 두 트랜잭션이 commit이 되지 않아도 발생
    1. user1이 어떤 데이터를 수정한다. 아직은 commit 하지는 않았다.
    2. user2는 그 사이에 user1이 수정한 데이터를 읽었다.
    3. user1이 commit 하는 대신, rollback을 수행했다.
    4. user1은 원복했고, user2는 user1이 변경할까 했었던 데이터를 들고 잘못된 판단/결정을 할 수 있는 상태에 놓였다.

    non-repeatable reads

    • 한 트랜잭션 내에서 값을 두 번 읽어봤는데, 값이 서로 다를 떄를 말한다.
    1. user1은 어떤 데이터를 읽었다. 아직은 commit하기 전이다.
    2. user2는 user1이 읽은 그 데이터를 수정하거나 삭제하고 commit까지 했다.
    3. user1이 그 데이터를 읽어들였는데, 원래 알고 있던 값과 다르다. (혹은 삭제 되었거나)

    phantom reads

    • 트랜잭션이 실행되는 도중, 새로운 데이터가 추가되거나 사라지는 경우를 말한다. (특히, 범위성 데이터와 연관)
    1. user1이 어떤 범위의 데이터를 읽었고, 아직은 commit하기 전이다.
    2. user2가 그 범위에 속하는 데이터를 추가했다.
    3. user1이 그 범위 데이터를 다시 읽었는데, 아까 없던 데이터가 발견되었다.
     

     

    Transaction Isolation Level 종류

    데이터의 정합성을 지켜주기 위해서는 결국 lock 메카니즘이 필요하다. 더 높은 수준의 정합성을 요구할 수록, 보다 복잡한 수준의 lock이 필요할 것이다. ANSI/ISO 표준에는 트랜잭션 격리 수준에는 다음의 4가지가 정의되어 있다. (lock 기반으로 동시성을 제어하는 시스템을 기준으로 작성하였다. 즉, DBMS 제품마다 내부적으로 다소 다를 수도 있다 - 격리수준 또는 lock 메카니즘)

    Read Uncommitted

    • 데이터를 읽을 때 lock을 사용하지 않는다.
    • 데이터를 수정할 때는 트랜잭션이 완료될 때까지 lock을 사용한다.

    Read Committed

    • 데이터를 읽거나 쓸 때 lock이 사용된다.
    • 데이터를 수정할 때는 트랜잭션이 완료될 때까지 lock을 사용하한다.
    • 데이터를 읽을 때는 데이터를 읽은 즉시 lock을 해제한다.
    • range-lock을 관리하지 않는다.

    Repeatable Read

    • 데이터를 읽거나 쓸 때 lock이 사용된다.
    • 데이터를 읽거나 수정할 때 모두 트랜잭션이 완료될 때까지 lock이 사용된다.
    • range-lock을 관리하지 않는다.

    Serializable

    • 데이터를 읽거나 쓸 때 lock이 사용된다.
    • 데이터를 읽거나 수정할 때 모두 트랜잭션이 완료될 때까지 lock이 사용된다.
    • range-lock을 관리한다.

     

    Transaction Isolation Level별 data consistency 문제점간 관계

    격리레벨 DIrty Reads Non-Repeatable Reads Phantom Reads 효율성/성능
    Read Uncommitted O O O 매우 높음
    Read Committed X O O 높음
    Repeatable Read X X O 보통
    Serializable X X X 낮음

    내가 사용하는 DBMS에서 어떤 트랜잭션 격리수준을 제공하고, 각 트랜잭션 격리수준에서 발생할 수 있는 현상을 인지하는 것은 분명 도움이 된다. (채용 인터뷰에도 종종 사용되기도 하는 질문이기도 하다.) 

    댓글

    Designed by JB FACTORY