데이터베이스 시스템의 성능을 높이기 위해 여러 트랜잭션을 동시에 실행하면 데이터베이스 부정합 문제가 발생할 수 있습니다. 이번 글에서는 이러한 부정합 문제에 대해 알아보도록 하겠습니다.

Lost update

갱신 손실(lost update)는 동일한 데이터에 대해 트랜잭션이 수행한 쓰기 연산의 결과가 다른 트랜잭션의 쓰기 연산에 의해 사라지는 것을 말합니다.

Untitled.png

위 그림에서 T1에서 수정한 결과가 T2에 의해 사라진 모습을 확인할 수 있습니다. 갱신 손실 문제를 정리하면 다음과 같습니다.

  • 원인: 두 개 이상의 트랜잭션이 동시에 동일한 데이터를 수정
  • 결과: 쓰기 연산을 먼저 수행한 트랜잭션의 결과가 사라짐
  • 해결 방법: SERIALIZABLE 격리 수준, lock

Dirty read

더러운 읽기(dirty read)는 동일한 데이터에 대하여 트랜잭션이 수정하는 동안 다른 트랜잭션이 이를 읽는 것을 말합니다.

Untitled.png

위 그림에서 T1이 A를 수정하는 동안 T2이 A를 읽어 비즈니스 로직을 수행했습니다. 그러나 T1은 트랜잭션을 롤백하였고 결국 T2는 잘못된 값을 사용한 모습을 확인할 수 있습니다.

  • 원인: commit 되지 않은 데이터를 읽음
  • 결과: 잘못된 값을 사용
  • 해결 방법: READ COMMITED 격리 수준, lock

Unrepeatable read

반복가능하지 않은 읽기(unrepeatable read)는 동일한 데이터에 대하여 트랜잭션이 값을 읽은 후, 다른 트랜잭션이 값을 수정한 후 다시 읽을 때 처음 값과 다른 값을 읽는 것을 말합니다.

Untitled.png

위 그림에서 T2가 처음 읽은 이후 T1이 값을 수정하게 되고 다시 T2가 값을 읽자 처음 읽은 값과 다른 것을 확인할 수 있습니다.

  • 원인: 다른 트랜잭션이 읽은 데이터를 수정할 수 있음
  • 결과: 트랜잭션 내에서 동일한 데이터에 대한 일관성이 없음
  • 해결 방법: REPETABLE READ 격리 수준, lock

Phantom read

팬텀 읽기(phantom read)는 트랜잭션이 범위를 지정해서 데이터를 읽은 후, 다른 트랜 잭션이 동일한 범위에 새로운 데이터를 추가하거나 처음 트랜잭션이 동일한 범위로 읽으면 없었던 데이터가 조회되는 것을 말합니다.

Untitled.png

위 그림에서 T2가 테이블의 전체 값을 조회했을 때 A, B, C, D가 조회되었지만 T1이 R을 추가한 후 T2가 다시 조회했을 때 처음 결과와 달리 R이 추가된 모습을 확인할 수 있습니다.

  • 원인: 다른 트랜잭션이 읽은 범위에 값을 추가하거나 삭제할 수 있음
  • 결과: 트랜잭션 내에서 범위 조회 결과가 일관성이 없음
  • 해결 방법: SERIALIZABLE 격리 수준, lock

Unrepeatable read와 phantom read의 차이

데이터베이스 부정합 문제를 처음 접하면 unrepeatable read와 phantom read가 비슷하게 느껴져서 헷갈리는데요. 둘의 차이를 간단히 정리해보겠습니다.

  • Unrepeatable read: 존재하는 동일한 데이터의 결과가 조회 시점에 따라 다르다.
  • Phantom read: 범위로 조회했을 때 없던 데이터가 나타나거나 있었던 데이터가 사라진다.

즉, unrepeatable read는 이미 존재하는 데이터의 값이 달라지는 것을 말하며 phantom read는 없었던 데이터가 나타나거나 있었던 데이터가 사라지는 것을 말합니다.

마무리하며

이번 글에서는 동시성으로 인한 데이터베이스 부정합 문제 4가지에 대해 알아보았습니다. 데이터베이스 시스템에서는 이러한 문제를 해결하기 위한 동시성 제어 방법을 지원합니다. 이번 글이 동시성 제어 학습에 도움이 되었길 바랍니다. ☺️

카테고리:

업데이트:

댓글남기기