[DB] 트랜잭션과 격리 수준

hyunoi·2024년 12월 11일

Database

목록 보기
1/8
post-thumbnail

트랜잭션이란?


데이터베이스에서 하나의 논리적인 기능을 수행하기 위한 작업의 단위를 말한다.
쿼리를 사용하여 데이터베이스에 접근을 하는데 이 쿼리들을 하나로 묶는 단위가 트랜잭션이라고 할 수 있다.
즉, 끊기지 않고 한 번에 수행되어야 하는 연산들의 모음

트랜잭션이 어떠한 상황에서 쓰이는지 예시를 들어보자.

  1. A는 B에게 100만원을 계좌 이체한다.
  2. B에게는 계좌에 A에게서 받은 100만원이 들어온다.

하지만, 이 두 개의 행동이 하나의 트랜잭션으로 묶이지 않으면?

  1. A의 계좌에서 돈은 빠졌지만? B에게는 돈이 들어오지 않는다
    -> 작업 중간에 장애 발생
  2. A가 보낸 금액과 B가 받은 금액이 일치하지 않게 됨
    -> 데이터 불일치

등의 문제가 발생할 수 있게 되는 것이다.

이런 문제 발생을 막기 위해서 트랜잭션으로 한 번에 이루어져야 하는 연산을 한 묶음으로 만드는 것이다.
실행에 성공한다면 100% 성공하던지, 아니면 0% 실패하던지!

트랜잭션의 특징, ACID


원자성 (Atomic)

위에서 말한 '실행에 성공한다면 100% 성공하던지, 아니면 0% 실패하던지!' 이 말 그대로이다.
원자성은 트랜잭션과 관련된 일이 모두 수행되었거나 되지 않았거나를 보장한다.

일관성 (Consistency)

데이터베이스가 트랜잭션을 통해서 항상 신뢰하고 무결성을 보장하는 상태를 유지해야 한다.
수행 전 후로 데이터가 일관되어야 한다.

격리성 (Isolation)

둘 이상의 트랜잭션이 수행되고 있으면 어떤 트랜잭션이라도 다른 트랜잭션 연산 사이로 끼어들 수 없다.
격리성을 보장하는 것에는 격리 수준이 여러 개로 나뉘어져 원하는 방식으로 격리성을 보장할 수 있다.

지속성 (Durability)

성공적으로 수행된 트랜잭션, 수행이 끝난 트랜잭션은 데이터베이스에 영원히 반영되어야 한다.

커밋과 롤백


트랜잭션에서는 커밋과 롤백이 실행이 된다.

  • 커밋 (Commit)
    트랜잭션이 수행되며 변경된 내용이 데이터베이스에 영구적으로 저장된다.
    커밋이 시작되고, 커밋이 종료되면 하나의 트랜잭션이 실행된 것이다.

  • 롤백 (Rollback)
    트랜잭션 중 발생한 작업을 모두 취소하여 트랜잭션 발생 전의 상태로 되돌린다.
    오류가 발생하거나 조건이 충족되지 않을 경우 실행한다.

커밋과 롤백으로 인해서 데이터 무결성이 보장된다.

격리 수준 (Isolation Level)


트랜잭션은 서로의 연산 사이로 끼어들 수 없다.
하지만 데이터베이스에는 여러 사용자가 같은 데이터에 접근을 해야 한다.

그러면 서로의 연산 사이로 끼어들지 않기 위해서는 그냥 순서대로 트랜잭션을 실행하면 되는건가?
이러면 성능이 매우 나빠지기 때문에 트랜잭션을 병렬로 사용한다.
하지만 이 과정에서 아래와 같은 문제들이 발생할 수 있다.

더티 리드 (Drity Read)

한 트랜잭션이 실행 중일 때 다른 트랜잭션의 아직 커밋되지 않은 행의 데이터를 읽는 경우에 Dirty Dead가 발생한다.

아래와 같은 상황에서 문제가 발생할 수 있다.

  1. 트랜잭션 A가 데이터를 변경하고 커밋하지 않은 상태에서 트랜잭션 B가 변경된 데이터를 읽는다.
  2. 그런데 트랜잭션 A가 커밋하지 않은 상태에서 롤백을 한다면?
  3. 트랜잭션 B는 변경하지 않았어야 하는 데이터가 변경된 상태로 읽고 처리를 하므로 더티 리드가 발생한다.

반복 불가능한 조회 (Non-repeatable Read)

같은 트랜잭션 내에서 같은 데이터를 조회했는데 서로 값이 다른 경우이다.

팬텀 리드 (Phantom Read)

한 트랜잭션 내에서 동일한 쿼리를 보냈을 때 조회의 결과가 다른 경우이다.


SERIALIZABLE

  • Level 3. 가장 높은 격리 수준
  • 트랜잭션을 들어오는 순서대로 실행한다.
  • 여러 트랜잭션이 동일한 데이터에 동시에 접근이 불가능하다.
  • 다른 트랜잭션이 특정 데이터에 대해 일어난다면 기다려야 한다.
  • 교착 상태가 제일 많이 일어나고, 성능이 떨어지는 격리 수준이다.

REPEATABLE_READ

  • Level 2
  • 하나의 트랜잭션이 수정항 행을 다른 트랜잭션이 수정할 수 없도록 막아준다.
  • 하지만 새로운 행을 추가하는 것은 막지 않는다.
  • 이후에 추가된 행을 발견할 수도 있다.

-> 팬텀 리드가 발생할 가능성이 있다.

READ_COMMITTED

  • Level 1. 가장 많이 사용되는 격리 수준
  • 다른 트랜잭션이 커밋하지 않은 데이터는 읽을 수 없다.
  • 어떤 트랜잭션이 접근한 행을 다른 트랜잭션이 수정할 수 있다.

-> 팬텀 리드와 반복 불가능한 조회가 발생할 가능성이 있다.

READ_UNCOMMITTED

  • Level 0. 가장 낮은 격리 수준
  • 트랜잭션에서 아직 커밋하지 않은 데이터를 다른 트랜잭션이 읽을 수 있다.

-> 팬텀 리드와 반복 불가능한 조회, 더티 리드가 발생할 가능성이 있다.

이 블로그에 트랜잭션 시에 일어나는 세 가지 문제에 대해 자세하게 설명되어 있다.
(사진이 매우 좋음...)


🦴 참고

https://hudi.blog/transaction-isolation-level/
https://nice-engineer.tistory.com/entry/%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4-%ED%8A%B8%EB%9E%9C%EC%9E%AD%EC%85%98%EC%9D%98-%EA%B2%A9%EB%A6%AC-%EC%88%98%EC%A4%80

0개의 댓글