[데이터베이스] Transaction Isolation Level

Yoon Uk·2023년 8월 23일
0

데이터베이스

목록 보기
18/20
post-thumbnail

참고 - YouTube: 쉬운코드

Transaction들이 동시에 실행될 때 발생 가능한 이상 현상isolation level에 대해 알아보겠습니다.

1. 이상 현상

1) Dirty Read

Dirty Read은 한 트랜잭션이 아직 Commit 되지 않은 변화를 읽었을 때 발생합니다.

2) Non-repeatable Read

Non-repeatable Read는 한 데이터를 두 번(여러 번) 읽었는데 그 값이 달라지는 현상입니다.
다른 말로 Fuzzy Read 라고도 부릅니다.

이는 트랜잭션의 속성 중의 하나인 Isolation 속성 관점에서 일어나선 안되는 현상입니다.
여기서 Isolation 속성이란 여러 트랜잭션이 동시에 실행되더라도 각각의 트랜잭션이 혼자 실행되는 것 처럼 실행되어야 한다는 속성입니다.

3) Phantom Read

Phantom Read는 없던 데이터가 생기는 현상입니다.

2. Isolation Level

표준 SQL 기준으로 설명하겠습니다.

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

따라서 이러한 단점을 어느정도 극복하기 위해 일부 이상 현상은 허용하는 몇 가지 level을 만들어 사용자(개발자)가 필요에 따라서 적절하게 선택할 수 있도록 한 결과가 Isolation Level(고립 수준)입니다.

트랜잭션 고립 수준이란 데이터베이스에서 동시에 여러 트랜잭션이 실행될 때, 어떤 트랜잭션이 다른 트랜잭션에서 변경하거나 조회하는 데이터를 볼 수 있게 할지를 정하는 것입니다.

Isolation LevelDirty ReadNon-repeatable ReadPhantom Read
Read uncommittedOOO
Read committedXOO
Repeatable readXXO
SerializableXXX

1) Read uncommitted

  • 위의 이상현상들을 모두 허용하는 단계입니다.
  • 가장 자유롭지만 이상 현상에 가장 취약합니다.
  • 동시성이 가장 높아져서 전체 처리량은 가장 높습니다.

READ UNCOMMITTIED는 가장 낮은 트랜잭션 고립 수준입니다.
이 수준에서는 한 트랜잭션이 아직 커밋되지 않은 데이터를 다른 트랜잭션에서 읽을 수 있습니다. 이를 더티 리드라고 합니다. 더티 리드는 데이터의 일관성을 해치는 문제입니다.

예를 들어, 한 트랜잭션이 A 계좌에서 B 계좌로 100만원을 이체하는 작업을 하고 있습니다. 이 때, 다른 트랜잭션이 B 계좌의 잔액을 조회하면, 아직 커밋되지 않은 100만원이 반영된 결과를 볼 수 있습니다. 만약 첫 번째 트랜잭션이 롤백된다면, 두 번째 트랜잭션은 잘못된 데이터를 읽은 것이 됩니다.

READ UNCOMMITTIED는 동시성은 높지만, 일관성은 매우 낮은 트랜잭션 고립 수준입니다. 따라서, 실제로 사용되는 경우는 거의 없습니다. 데이터의 정확성이 중요한 애플리케이션에서는 READ UNCOMMITTIED를 사용하지 않는 것이 좋습니다.

2) Read committed

  • commit 된 데이터만 읽습니다.
  • 따라서 Dirty Read는 허용하지 않습니다.

READ COMMITTED는 트랜잭션이 커밋된 데이터만 읽을 수 있도록 하는 고립 수준입니다.
즉, 다른 트랜잭션이 변경한 데이터를 읽으려고 하면 해당 트랜잭션이 커밋될 때까지 기다려야 합니다. 이렇게 하면 더티 리드(Dirty Read)라고 하는 현상을 방지할 수 있습니다.

READ COMMITTED 고립 수준은 일관성 있는 읽기를 보장하지는 않습니다.
즉, 같은 트랜잭션에서 같은 데이터를 여러 번 읽어도 같은 결과가 나오는 것이 아닙니다.

예를 들어, 트랜잭션 A가 데이터를 읽은 후에 트랜잭션 B가 해당 데이터를 변경하고 커밋한다면, 트랜잭션 A가 다시 데이터를 읽으면 변경된 값을 볼 수 있습니다. 이렇게 하면 Non-Repeatable Read라고 하는 현상이 발생할 수 있습니다.

3) Repeatable read

  • Phantom Read만 허용합니다.

REPEATABLE READ는 자신의 데이터에 설정된 공유락과 배타락을 트랜잭션이 종료될 때까지 유지하여 다른 트랜잭션이 자신의 데이터를 갱신(Update)할 수 없도록 합니다.

이로 인해 Non-repeatable Read 현상을 방지할 수 있습니다. 하지만 다른 트랜잭션이 새로운 데이터를 삽입(Insert)할 수 있으므로 Phantom Read 현상이 발생할 수 있습니다.

4) Serializable

  • 모든 위의 3가지 이상현상들을 모두 허용하지 않습니다.
  • 또한 위 3가지 현상 뿐만 아니라 아예 이상한 현상 자체가 발생하지 않는 level 입니다.

SERIALIZABLE 고립 수준은 데이터의 일관성을 최대한 보장하지만, 동시성이 매우 낮아 성능 저하가 발생할 수 있습니다. 따라서, 특별한 상황이 아니라면 사용하지 않는 것이 좋습니다.

3. 이상 현상 + α

위의 3가지 이상현상의 정의가 모호하고
이상 현상은 3가지 외에도 더 있다는 비판과 함께
아래의 이상 현상들이 추가되었습니다.

1) Dirty Write

commit 되지 않은 데이터를 write 한 현상입니다.

RollBack 시 정상적인 recovery는 매우 중요하기 때문에 모든 Isolation Level에서 Dirty Write를 허용하면 안됩니다.

2) Lost Update

Update가 되었지만 DB에 반영되지 않는 현상입니다.

3) Dirty Read 확장판

Dirty Read는 commit 되지 않은(유효하지 않은) 데이터를 읽는 현상입니다.

RollBack이 되지 않아도 Dirty Read가 될 수 있는 현상입니다.

4) Read Skew

skew : 비스듬한, 비뚤어진 이라는 뜻

inconsistent한 데이터를 읽는 현상입니다.
즉, 데이터가 불일치한 읽기가 발생하는 현상입니다.

Non-repeatable Read와 비슷합니다.

5) Write Skew

inconsistent한 데이터를 쓰는 현상입니다.
즉, 데이터가 불일치한 쓰기가 발생하는 현상입니다.

6) Phantom Read 확장판

Phantom Read는 없던 데이터가 생기는 현상입니다.

꼭 같은 조건을 두 번 읽는 상황이 아니라도 이상 현상이 발생할 수 있는 현상입니다.

4. Isolation Level + α

Snapshot Isolation

위의 추가된 이상현상과 더불어 이전의 Isolation Level이 상업적인 DBMS에서 사용하는 방법을 반영해 구분되지 않았다는 비판과 함께 추가된 Isolation Level입니다.

위에서 정의한 4가지 Isolation Level은 이상 현상 3가지를 정의한 뒤에 그 이상 현상들 중에 어느 정도를 허용할 것인지에 따라서 level을 구분했습니다.
이와 다르게 Snapshot Isolation은 Concurrency Control이 어떻게 작동할 지, 그 구현을 바탕으로 정의된 Isolation Level 입니다.

Snapshot Isolation은 아래와 같이 작동합니다.

  1. A 트랜잭션이 시작하는 시점에 snapshot A를 찍습니다.
  2. B 트랜잭션이 시작하는 시점에 snapshot B를 찍습니다.
  3. B 트랜잭션이 commit을 하면 B 트랜잭션의 결과가 DB에 저장됩니다.
  4. A 트랜잭션은 snapshot A를 찍은 시점의 데이터를 기준으로한 결과를 commit 합니다.
  5. A 트랜잭션의 결과가 B 트랜잭션의 결과를 덮어씌워 B 트랜잭션의 결과는 사라지게 됩니다.

Snapshot Isolation은 같은 데이터에 write-write를 할 때 먼저 commit 된 결과만 인정을 해줍니다.
위의 경우에서는 B 트랜잭션의 결과만 인정되고 A 트랜잭션은 abort 처리됩니다.

참고

쉬운코드

0개의 댓글