Read Phenomena in Transactions

2024. 6. 4. 00:56데이터베이스/데이터 지식


Read Phenomena

 

먼저 트랜잭션의 격리 수준(isolation level)이란 어떤 트랜잭션이 데이터를 조회할 때,

다른 트랜잭션이 해당 데이터를 변경했을 때 - 영향을 얼마나 가져갈 것이냐 하는 것입니다.

 

쉽게 말해 내가 A라는 데이터를 읽고 난 후, 다른 사람이 해당 데이터를 수정했을 때

다시 A 데이터를 읽으면 처음에 읽었던 것을 읽을 것이냐, 아니면 수정된 걸 읽을 것이냐 하는 수준입니다.

 

ANSI, ISO/IEC의 SQL-92 표준을 보면 격리 수준 4가지와 이에 따른 현상 3가지가 있습니다.

격리 수준으로는

  • READ UNCOMMITTED
  • READ COMMITED
  • REPEATABLE READ
  • SERIALIZABLE

이 있고,

 

현상으로는 

  • Dirty read
  • Non-repeatable read
  • Phantom

이 있습니다. 그리고 이 3가지 현상을 다른 말로 - 읽기 현상(read phenomena)이라고 표현합니다.

 

낮은 수준일수록 더 많은 읽기 현상이 등장할 수 있습니다.
그러나 높은 수준일수록 많은 시스템 자원과 성능을 요구하기 때문에, 마냥 좋다 나쁘다라는 기준은 없긴 합니다.

따라서 본인이 어느 정도 타협해서 적절한 수준을 적용하면 좋습니다.

여담으로 필자는 실무에 있을 때 기본적으로 Non-repeatable read 까지 막았으며, 필요 시 phantom까지 막긴 했습니다.

 

 

아래부터 설명 이미지에 나오는 Transaction은 편의상 T로 부르겠습니다.

 

 

 

 

 


Dirty Read

 

가장 낮은 격리 수준인 READ UNCOMMITTED에서 발생하는 현상입니다.

이는 커밋되지 않은 결과를 읽는 것으로, 커밋이나 롤백 상관 없이 데이터가 변경되면 그대로 읽습니다.

 

 

 

 

주요 쟁점은, T1이 모종의 이유로 green으로 업데이트한 걸 롤백해서 다시 brown으로 복구했음에도 -

T2는 신경쓰지 않고 green을 계속 쓴다는 점입니다.

 

사실 롤백은 데이터에 어떤 문제를 발견했기 때문에, 다음 과정을 계속 진행하지 못해 다시 회귀하는 노력이라

그 문제가 되는 과정의 데이터를 쓴다면 어떤 문제를 또 야기할 지 모릅니다.

따라서 대부분의 어플리케이션에는 적어도 Dirty Read를 방지하려고 격리 수준을 높이긴 합니다.

 

 

 

 

 

 

 


Avoid Dirty Read

 

격리 수준을 READ COMMITTED까지 올리면 Dirty Read 현상을 피할 수 있습니다.

이때 READ COMMITTED는 커밋된 결과만을 읽는 것입니다.

 

 

 

 

T2는 green이 아직 커밋되지 않았으므로 여전히 brown을 읽게 됩니다.

따라서 T1이 롤백했을 때도 brown을 사용하게 될 것입니다.

 

 

 

 

 


Non-repeatable Read

 

두 번째 격리 수준인 READ COMMITTED에서 발생하는 현상입니다.

 

 

 

 

T2는 brown을 계속 쓰다가, T1이 커밋한 이후부터는 green을 사용합니다.

 

쉽게 생각해보면, 커밋이라는 행위는 데이터가 완전하다는 결정에 의해 내리기 때문에

T2가 변경된 데이터를 읽는 게 당연해보여서, 문제가 되는 것 같지 않아 보입니다.

 

하지만 하나의 트랜잭션 내에서 동일한 데이터를 여러 번 조회했을 때마다

상태값이 달라지는 걸 원하지 않는다고 생각해보면 문제가 생길 수 있겠죠.

 

예를 들어 포도의 상태를 보고 포장하는 기계를 생각해봅시다.

 

카메라는 포도의 상태를 읽고 포도 테이블의 색깔을 업데이트 한다면,

로봇 손은 테이블에서 색깔이 brown인 것만 포장을 한다고 해봅니다.

 

카메라가 먼저 포도를 brown으로 만들고 트랜잭션을 종료한 상황에서

T1 : 카메라가 다시 포도 테이블을 방문해서 brown 색깔을 읽습니다.

T2 : 로봇 손도 포도 테이블을 방문해서 brown 색깔을 읽습니다.

 

T2 : 로봇 손이 포장지에 포도를 넣습니다.

T1 : 카메라가 재차 포도를 보니 green으로 인식해서 포도 테이블에서 색깔을 green으로 업데이트 및 커밋합니다.

T2 : 로봇 손이 포도 테이블을 방문하니 green 색깔이어서 리본을 묶지 않고 보냅니다.

 

관리자가 결과를 보니 이도저도 아닌 결과물이 돌아댕기고 있습니다.

포장을 아예 안하던지, 하던지 둘 중 하나를 예상했기 때문이죠.

 

 

 

 

 


Avoid Non-repeatable Read

 

격리 수준을 REPEATABLE READ까지 올리면 Non-repeatable Read 현상을 피할 수 있습니다.

동일한 행을 여러 번 읽어도 동일한 결과를 주는 것입니다.

 

 

T1이 커밋했음에도 T2는 여전히 brown을 읽습니다.

 

 

 

 

 

 


Phantom Read

 

세 번째 격리 수준인 REPEATABLE READ에서 발생하는 현상입니다.

이전 Non-repeatable Read 현상이 행 단위가 아닌 범위로 확장한 것으로 이해하면 쉽습니다.

 

 

 

 

 

 

 

 


Avoid Phantom Read

격리 수준을 SERIALIZABLE까지 올리면 Non-repeatable Read 현상을 피할 수 있습니다.

 

 

사실 필자는 Phantom Read 현상을 마주칠 기회가 없었긴 했습니다.

그리고 해당 격리 수준은 시스템 자원을 꽤나 잡아먹기 때문에 - 보통 이 수준까지는 올리지 않았습니다.