sol 개발 블로그 로고
Published on

Transaction Isolation Level 4가지

Authors
  • avatar
    Name
    Chan Sol OH
    Twitter

목차

이번 포스팅은 DB Transaction의 Isolation에 관한 포스팅이다. Transaction의 개요를 알고 싶다면, Transaction은 무엇일까? 포스팅을 참고하길 바란다.

Transaction이 동시에 실행될 때 발생하는 문제들.

세가지 문제 상황을 가정해서 상상해보자.

Dirty read

Transactions dirty read

위 상황은 transaction1,2가 동시에 잘 실행되다가 갑자기 transaction2에 문제가 발생하여 rollback하면서 y의 값이 70에서 처음의 20으로 바뀌었다. transaction2의 rollback으로 인해 transaction1의 read(x)의 결과는 70이 아니라 20으로 바꿔야한다. 즉 transaction1이 유효하지 않은 값을 읽어버린 것이다.

위와 같이 commit되지 않은 데이터를 읽은 상황을 Dirty read라고 한다.

Non-repeatable read, Fuzzy read

또 다른 상황을 보자.

Transactions

위 상황은 transaction1이 변수 X를 두번 읽는 작업을 한 transaction에 수행했다. 그러나 transaction2의 작업으로 X값이 변화하여 transaction1이 다른 값을 읽게되었다.

여러 transaction이 실행되더라도 각각의 transaction은 마치 혼자서 실행되는 것과 동일해야하는 것이 transaction의 isolation 속성이기 때문에 만약 transaction1이 혼자 작업한다면 X는 동일하게 10이 읽혔어야한다. 하지만, transaction1이 다른 transaction의 영향을 받아 읽는 결과가 바뀌게 됐다.

위와 같이 isolation을 만족하지 못해서 같은 데이터 값을 읽을 때 다른 결과를 얻는 경우를 Non-repeatable read라고 한다.

Phantom read

Transactions

위 그림도 Isolation 관점에서 문제가 생긴 것이다.

Repeatable Read는 사용자가 조회하는 데이터를 외부 transaction으로부터 격리하지 못할 때 발생한다. 이를 막아서 데이터를 외부 transaction으로부터 격리한다고 해도 다른 데이터가 외부 transaction에 노출된다면, 사용자가 읽는 데이터의 범위가 외부로 인해 바뀔 수 있다. 이를 Phantom Read라고 한다.

위 그림은 transaction1이 v가 10인 데이터라는 범위를 조회하고 있다. 하지만, 첫 조회와 달리 transaction2로 인해 그 범위가 바뀌어서 첫 번째 조회와 두 번째 조회 결과가 달라지는 문제가 있다. Phantom read를 해결하려면 transaction이 있을 때마다 모든 데이터를 한 transaction에 종속시켜야하기 때문에 DB 성능이 떨어진다. 그렇기 때문에 repeatable read 수준의 격리 수준에서는 Phantom read를 허용한다.

Transaction Level의 등장

위와 같은 이상한 현상들이 발생하는 이유는 두 transaction이 동시에 수행되기 때문이고, 이를 방지하기 위해 제약사항을 추가하면 동시 처리 가능한 트랜잭션 수가 줄어들어 DB의 전체 처리량이 하락하게 된다. DB 처리량의 감소를 원하지 않는 다면 일부 이상한 현상을 허용하는 몇 가지 Level을 만들어서 사용자가 필요에 따라 적절하게 선택할 수 있게하는 것

  1. Read uncommitted

    • transaction은 uncommitted data를 읽을 수 있다. 심지어 rollback될 가능성이 있더라도!!
    • 제약사항을 두지 않고 DB의 처리량을 최대화하는 Level
  2. Read commited

    • transaction에서 동일한 row를 반복적으로 읽을 때, 다른 transaction의 commit으로 변화된 데이터를 읽을 수 있다
    • Dirty read 제한 & Non-repeatable read 발생 가능
  3. Repeatable read

    • transaction에서 동일한 row를 반복적으로 읽을 때, 동일한 값을 읽는 것을 보장
    • 하지만, 다른 row의 변화 방지는 보장하지 않기 때문에 Phantom read 발생 가능!
    • Non-repeatable read 제한
  4. Serializable

    • 모든 transaction은 isolated 보장하기 때문에 서로 간섭할 일이 없다.
    • Phantom read 포함 모든 이상 현상이 발생하지 않는 Level

이상한 현상을 정의하고 어디까지 허용할지를 결정하는 Level 애플리케이션 설계자는 isolation level을 통해 전체 처리향과 데이터 일관성 사이에서 어느 정도 거래를 할 수 있다.

SNAPSHOT Isolation type of MVCC

어떻게 데이터 일관성을 구현할지에 따라서 결정되는 level SNAPSHOT Isolation은 transaction이 실행되는 그 시점에 데이터를 따로 저장해둔다. 또한 transaction에서 write 작업은 바로 DB에 반영되는 것이 아니라 SNAPSHOT에 1차로 반영하게 된다.

위처럼 transaction을 진행하는 동안 SNAPSHOT에 데이터를 작성하고 읽는다렴, commit될 때까지 다른 transaction이 보는 DB는 변화가 없을 것이다. commit해서 DB가 변하면 다른 transaction이 시작하면 그 결과를 사용하게 된다.

만약 transaction 중에 다른 transaction의 작업이 완료돼서 Commit까지 했다면, SNAPSHOT과 DB의 상태가 많이 달라져있을 것이다. 이 경우 동일한 값에 쓰기 작업을 한 두 commit이 있을 때 먼저 commit한 transaction만 인정하고 나중에 commit한 transaction은 abort로 rollback해서 처음부터 다시 실행된다.

  1. transaction 시작 전에 commit된 데이터만 보임
  2. First committer가 우선되고, 나중 commit은 폐기된다.

실무에서 Isolation level

  1. MySQL은 표준과 동일한 isolation level을 적용한다.
  2. Oracle은 Read commited와 Serializable만 사용히고, Read uncommitted은 지원하지 않는다.
    • Oracle은 Repeatable read과 Serializable은 Serializable로 통칭해서 사용된다.
    • Oracle은 Serializable을 구현할 때 SNAPSHOT Isolation을 적용했다.
  3. SQL server도 표준에서 정의된 isolation level을 적용하고 추가로 SNAPSHOT Isolation을 지원한다.
  4. PostgreSQL도 표준에서 정의된 isolation level을 적용한다.
    • PostgreSQL은 표준에서 소개한 현상 뿐만 아니라 Serialization Anomaly라는 현상을 추가해서 level을 설명한다.
    • PostgreSQL의 Repeatable read는 SNAPSHOT Isolation을 적용했다.