DB | transaction isolation level

yeonk·2023년 10월 5일
0

database

목록 보기
30/34
post-thumbnail

transaction isolation level





학습 주제


  • 트랜잭션들이 동시에 실행될 때 발생 가능한 이상 현상들
  • isolation level





SQL 표준 이상 현상


SQL 표준에서 정의한 이상 현상 3가지는 아래와 같다.
예제를 통해 각각의 현상들을 알아보자.

  • Dirty Read
  • Non-repeatable Read
  • Phantom read





Dirty Read


Dirty Read는 Commit 되지 않은 변화를 읽어 발생하는 이상 현상이다.

예시를 통해 이해해보자.
데이터베이스에 X=10, Y=20이라는 값을 가지고 있고, 아래와 같은 스케줄로 2가지 트랜잭션을 사용하려고 한다.

위 상황에서는 어떤 문제가 발생했을까?

트랜잭션 1이 읽은 y=70 이라는 값은 롤백되어 유효하지 않은 값이다.
유효하지 않은 y 값을 읽어 x 값을 업데이트한 것이다.
그렇기 때문에 x 값 역시 유효하지 않은 값으로 볼 수 있다.





Non-repeatable Read


Non-repeatable Read는 같은 데이터를 여러번 읽었을 때 값이 달라지는 현상을 말한다.
Fuzzy Read 라고도 한다.

예시를 통해 이해해보자.
데이터베이스에 X=10이라는 데이터가 있고, 아래와 같은 스케줄로 2가지 트랜잭션을 사용하려고 한다.

어떤 문제가 발생한걸까?

트랜잭션 1은 하나의 트랜잭션 내에서 같은 데이터를 두 번 읽었는데 그 값이 다른 문제가 발생했다.
이 현상은 isolation 관점에서 보면 일어나면 안되는 일이다.
isolation 속성은 여러 트랜잭션이 동시에 실행돼도, 각각의 트랜잭션이 마치 하나만 동작하는 것처럼 실행되어야 한다는 것을 의미한다.





Phantom Read


Phantom Read는 없던 데이터가 생기는 현상을 말한다.

예시를 통해 이해해보자.
데이터베이스에 tuple1(...,v=10), tuple1(...,v=50)이라는 데이터가 있고, 아래와 같은 스케줄로 2가지 트랜잭션을 사용하려고 한다.

어떤 문제가 발생한걸까?

트랜잭션1이 동일한 조건으로 값을 두 번 읽었는데 결과 값이 추가되었다.
마찬가지로 isolation 관점에서 이상 현상으로 볼 수 있다.

예시와 같이 기존 값을 update하는 것이 아니라 동일 조건으로 insert해도 해당 문제가 발생할 수 있다.





(SQL 표준) 격리 레벨


앞선 3개의 현상들은 이상한 결과와 데이터 불일치를 발생시키기 때문에 발생하지 않는 것이 좋다.

이런 이상한 현상들이 모두 발생하지 않게 만들 수 있지만, 그러면 제약사항이 많아져서 동시 처리 가능한 트랜잭션 수가 줄어들어 결국 DB 전체 처리량(throughput)이 하락하게 된다.

이러한 부분을 고려하여 '일부 이상한 현상은 허용하는 몇 가지 level을 만들어서 사용자가 필요에 따라서 적절하게 선택할 수 있도록 하자'는 아이디어를 도출하게 된다.
이걸 적용한 것이 격리 레벨(isolation level)이다.



격리 레벨은 3개의 현상 중에 몇 개의 현상을 허용하는지에 따라 아래와 같이 구분할 수 있다.

레벨이 엄격해질수록 허용하지 않는 현상들이 증가하는 특성을 가진다.

read uncommitted은 가장 자유롭지만 이상 현상에 가장 취약하며, 동시성은 높아 전체 처리량은 가장 높은 특성을 가진다.

read committed은 커밋된 데이터만 읽는다.

serializable은 위 세 가지 현상을 포함한 이상 현상 자체가 발생하지 않는 레벨을 의미한다.

세 가지 이상 현상을 정의하고 어떤 현상을 허용하는지에 따라서 각각의 격리 레벨이 구분된다. 그렇기 때문에 애플리케이션 설계자(개발자)는 격리 레벨을 통해 전체 처리량과 데이터 일관성 사이에서 어느 정도 거래(trade) 를 할 수 있다.





SQL 표준 비판


앞선 내용들은 1992년 11월에 발표된 SQL 표준에서 정의된 내용이다.
그런데 이 내용을 비판하는 논문이 등장했고, 주요한 주장은 아래 3가지이다.

1. 세 가지 이상 현상의 정의가 모호하다.
- 예를 통해서 설명했을 뿐 일반화해서 표현을 한다면 어떤 형태인 것인지, 그 정의가 모호하다

2. 이상 현상은 세 가지 외에도 더 있다.

3. 상업적인 DBMS에서 사용하는 방법을 반영해서 isolation level을 구분하지 않았다.



각 비판에 대한 내용들을 하나씩 살펴보자.





1. 모호한 이상 현상 정의


세 가지 이상 현상의 정의가 모호하다.



확장된 Dirty Read


논문에서는 더티 리드의 개념이 더 확장적인 개념으로 쓰여야한다고 주장한다.

확장적인 개념은 어떤 것을 의미하는 걸까?
앞서 SQL 표준을 기반으로 설명한 Dirty Read는 의존하는 트랜잭션 작업의 Rollback을 고려하여 설명하였다.
하지만 Dirty Read는 의존하고 있는 트랜잭션의 작업이 롤백 되어야만 발생하는 것일까?

아니다. 롤백 되지않아도 Dirty Read가 발생할 수 있다.

그 예제를 살펴보자.

위 예시에서는 의존하는 트랜잭션 abort가 발생하지 않았음에도, 커밋되지 않은 값을 읽어 데이터 불일치 문제가 발생한 것을 볼 수 있다.



확장된 Phantom Read


논문에서는 팬텀 리드도 더 넓은 개념이어야한다고 주장한다.

SQL 표준에 기반한 팬텀 리드는 같은 조건으로 여러번 읽었을 때, 데이터가 추가로 읽히는 현상이라고 설명했다.

하지만 더 확장적인 개념으로도 볼 수 있다.
아래 예시를 보자.

(cnt 는 v 가 10보다 큰 값을 가지는 튜플의 수를 의미한다)

트랜잭션 1이 v 가 10보다 큰 값을 조회했을 때는 아무 결과가 나오지 않았다. 하지만 cnt를 조회했을 때는 1이 조회되었다.
즉, 데이터 불일치가 발생한 것이다.

이와 같이 같은 조건으로 여러번 읽는 경우가 아니더라도, 연관된 데이터가 있는 경우에는 어떤 데이터가 추가가 됐을 때 이상 현상이 발생할 수 있다(팬텀 리드).





2. 추가 이상 현상


이상 현상은 세 가지 외에도 더 있다.



Dirty Write

여러 트랜잭션이 write를 할 때 롤백을 할 때, 발생할 수 있는 이상 현상

예시를 보자.

트랜잭션 1이 x를 0으로 되돌려놓으면 트랜잭션2의 작업이 사라진다.
그래서 롤백하지 않았다고 가정해보자.

그 상태에서 트랜잭션 2가 작업을 롤백한다면? 이번에는 x를 10으로 되돌려 놓는 문제가 발생한다.

롤백 시 정상적인 recovery는 매우 중요하기 때문에 모든 격리 레벨에서 dirty write를 허용하면 안 된다.



Lost Update

다른 트랜잭션의 업데이트를 덮어 쓰는 현상 (update 유실)

위 예시에서는 트랜잭션 2의 업데이트 작업이 사라지는 문제가 발생하는 것을 볼 수 있다.

만약 위와 같은 순서가 아니라 각 트랜잭션의 작업이 순차적으로 실행되었다면 값은 250이 되었을 것이다.



Read Skew

데이터가 불일치한 읽기가 발생하는 현상

x와 y를 통장 총액이라고 생각해보면, x + y 값이 동일해야하는데 해당 예시에서는 그렇지 않다.
이 부분에서 데이터 불일치 문제가 발생한 것을 알 수 있다.



Write Skew

서로 다른 데이터를 write 했음에도 데이터 불일치를 불러오는 현상

트랜잭션 1과 트랜잭션 2가 각각 다른 데이터를 write 하였지만, 제약 조건을 깨는 데이터 불일치를 발생시키게 되었다.

만약 이 DBMS 가 serializable 하게 잘 구현되어 있다면 트랜잭션 2 를 커밋하려고 하면 제약 조건에 걸려서 커밋이 안되고 어보트 될 것이다.
하지만 그게 아니라면 위 예시와 같이 제약 사항을 깨는 데이터 불일치를 만드는 현상이 발생할 수 있다.





3. 상업적인 DBMS 고려


상업적인 DBMS에서 사용하는 방법을 반영해서 isolation level을 구분하지 않았다.

논문에서 상업적인 DBMS의 방법을 고려하지 않은 것을 비판하면서 소개하는 격리 레벨이 있는데 바로 스냅샵 아이솔래이션 이다.

기존 레벨은 이상 현상 3가지를 정의하고 얼마만큼 허용하는지에 따라 레벨을 구분하였으나, 스냅샷 아이솔레이션은 동시성 제어가 어떻게 동작할지, 그 구현을 바탕으로 정의한 것이다.
즉, 구현 방식에 기반해서 정의한 레벨이다.



Snapshot Isolation

동시성 제어 구현 방식에 기반해서 정의한 격리 레벨.
mvcc(multi version concurrency control)의 한 종류이다.

  • 스냅샷 : 특정 시점에서의 형상

  • 특정 시점: 트랜잭션이 시작하는 시점

  • 특징

    • 데이터베이스에 바로 적용하지 않고 스냅샷에 적용한다.
    • 트랜잭션 시작 전에 커밋된 데이터만 보인다.
    • 첫번째 커밋을 우선하여 인정한다.

이번에도 예제를 살펴보자.

만약 트랜잭션 1의 작업 내용을 커밋한다면 로스트 업데이트가 발생할 것이다.

하지만 스냅샷 아이솔레이션은 같은 데이터에 대해 write 했을 때, 먼저 커밋한것만 인정하는 특징이 있다.

인정 받지 못한 작업 내용은 어보트 되고, 스냅샷은 폐기한다.





RDBMS의 격리 레벨


실무에서 사용되는 RDBMS에서는 어떻게 적용하고 있을까?

주요 RDBMS는 SQL 표준에 기반해서 isolation level을 정의한다.
하지만 RDBMS 마다 제공하는 isolation level이 다르다.
그리고 같은 이름의 isolation level이라도 동작 방식이 다를 수 있다.

그렇기 때문에 사용하는 RDBMS의 isolation level을 잘 파악해서 적절한 isolation level을 사용할 수 있도록 해야 한다.





참고 자료


[쉬운 코드] transaction isolation level

[표준 SQL 92] SQL transactions : 67 page

A Critique of ANSI SQL Isolation Levels

0개의 댓글