ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [DB] 트랜잭션의 모든 것
    데이터베이스 2024. 6. 28. 10:48

    트랜잭션이란?

    트랜잭션(Transaction)은 데이터베이스의 상태를 변환시키는 하나의 논리적 기능을 수행하기 위한 작업의 단위 또는 한꺼번에 모두 수행되어야 할 일련의 연산들을 의미한다.

     

    특징

    • 트랜잭션은 데이터베이스 시스템에서 병행 제어 및 회복 작업 시 처리되는 작업의 논리적 단위이다.
    • 사용자가 시스템에 대한 서비스 요구 시 시스템이 응답하기 위한 상태 변환 과정의 작업단위이다.
    • 하나의 트랜잭션은 Commit되거나 Rollback된다.

     

    ACID

    • 원자성(Atomicity)
      • 트랜잭션이 DB에 모두 반영되거나 전혀 반영되지 않아야 한다
    • 일관성(Consistency)
      • 트랜잭션의 작업 처리 결과는 항상 일관성 있어야 한다
    • 독립성(Isolation)
      • 둘 이상의 트랜잭션이 동시에 병행 실행되는 경우 어느 하나의 트랜잭션 실행중에 다른 트랜잭션의 연산이 끼어들 수 없다
    • 지속성(Durability)
      • 성공적으로 트랜잭션은 완전히 완료될 때까지 다른 트랜잭션에서 수행 결과를 참조할 수 없다

     

     

    연산(commit, rollback)

     

    커밋(COMMIT)

     

     

    • 트랜잭션의 수행이 성공적으로 완료되었음을 선언하고 그 결과를 최종 DB에 반영
    • 모든 작업들을 정상적으로 처리했다고 확정하는 명령어
    • 처리 후 데이터베이스에 저장
    • 처리 후 하나의 트랜잭션 과정 종료

     

     

    롤백(ROLLBACK)

    • 트랜잭션 수행이 실패했음을 선언하고 작업을 취소하는 연산
    • 트랜잭션이 수행되는 도중 일부 연산이 처리되지 못한 상황이라면 ROLLBACK 연산을 실행
    • DB를 트랜잭션 수행 전과 일관된 상태로 되돌려야 함
    • 트랜잭션의 일부가 정상적으로 처리가 완료 했더라도 트랜잭션이 행한 연산 취소 -> 원자성
    • 되돌아 갈때 마지막 커밋 완료한 시점으로 되돌아 간다

     

     

    상태

     

    활동(Active)

    • 트랜잭션이 실행 중인 상태

     

    부분적 완료(Partially Committed)

    • 트랜잭션의 마지막 연산까지 실행
    • 커밋 연산이 실행되기 직전의 상태

     

    완료(Committed)

    • 트랜잭션이 성공적으로 완료하여 종료되어서 커밋 연산을 실행한 후의 상태

     

    실패(Failed)

    • 트랜잭션 실행에 오류가 발생하여 중단된 상태

     

    철회(Aborted)

    • 트랜잭션이 오류가 생기거나 비정상적으로 종료 되어 롤백 연산을 수행한 상태

     

     

    복구

     

    UNDO, REDO

     

    REDO는 다시 하다 라는 뜻

    UNDO는 원상태로 돌리다 라는 뜻

     

    한마디로 REDO는 무언가를 다시하는 것 UNDO는 무언가를 되돌리는 것

     

     

    REDO

    • 이미 커밋한 트랜잭션의 수정을 재반영하는 복구 작업
    • 사용자가 했던 작업을 그대로 다시 복구

     

    UNDO

    • 트랜잭션이 어떤 이유이던지 정상적으로 종료 될 수 없게 되면 트랜잭션이 변경한 페이지들은 원상 보구 되어야 함
    • 작업을 원상태로 복구

     

     

    트랜잭션 격리 수준(Isolation level)

    한 트랜잭션이 사용 중인 데이터에 대해 다른 트랜잭션의 접근 허용 정도를 결정하는 것을 말함

     

    트랜잭션 격리 수준은 아래와 같이 4단계로 나뉜다

    • Read Uncommitted(Level 0)
    • Read Committed(Level 1)
    • Repeatable Read(Level 2)
    • Serializable(Level 3)

    격리 수준이 높아 질 수록 동시성은 낮아지지만, 데이터 일관성은 높아진다

     

     

     

    Read Uncommitted(Level 0)

     

    커밋되지 않은 데이터를 다른 트랜잭션이 조회할 수 있도록 허용하는 격리 수준

    커밋되지 않은 데이터를 조회함으로써 생기는 Dirty Read 문제가 발생할 수 있음

     

     

    Dirty Read

    한 트랜잭션의 다른 트랜잭션의 커밋되지 않은 변경사항을 조회하는 것

     

    예시)

     

    은행 데이터베이스라고 가정을 해보자

    • 읽기 트랜잭션 T1
    • 쓰기 트랜잭션 T2
    • amount = 1000 이라고 하자

     

    1. 우선 T2가 amount의 1000을 3000으로 변경한다 (아직 커밋되지 않았음)
    2. 읽기 트랜잭션 T1이 amount을 읽는다 -> 여기서 변경된 값 3000을 읽게 된다 즉, Dirty Read 발생한 것이다
    3. 정상적이지 않게 T2가 갑자기 롤백이 일어나서 T2의 변경 사항이 무효가 되어 버린다 amount 는 1000으로 복구
    4. T1은 3000의 값으로 작업이 계속 된다 -> 문제

     

     

    이러한 Dirty Read는 트랜잭션 격리 수준을 Read Committed 로 격상함으로써 해결할 수 있다

     

     

     

     

    Read Committed(Level 1)

     

    트랜잭션의 변경 작업을 외부에서 조회할 수 없게 하는 격리 수준이다

    커밋이 완료된 데이터만 조회 가능해서 Dirty Read 문제를 해결 할 수 있다

    이 격리 수준에서는 Non-Repeatable Read 문제가 발생할 수 있다

     

    예시)

     

    T2는 amount의 값인 1000을 2000으로 변경한다(아직 커밋되지 않음)

    읽기 트랜잭션 T1이 amount을 조회한다 -> 이전 커밋인 1000을 조회

    T1은 amount 1000을 가지고 작업을 계속한다 -> Dirty Read 문제 해결

     

     

    Non-Repeatable Read

    처음 데이터를 조회 후 다시 데이터를 조회 할 때 첫 조회 결과와 다른 조회 결과를 얻는 현상

     

    예시)

     

    1. 읽기 트랜잭션 T1이 amount을 조회  amount = 1000
    2. 쓰기 트랜잭션인 T2가 amount를 3000으로 변경하고 커밋한다
    3. T1이 amount를 다시 조회한다 amount =3000 -> 이전 조회시에 결과가 다른 Non-Repeatable Read 발생

     

    이러한 Non-Repeatable Read는 트랜잭션 격리 수준을 Repeatable Read 로 격상함으로써 해결할 수 있다

     

     

     

     

    Repeatable Read(Level 2)

     

    트랜잭션 내에서 조회한 데이터의 값이 항상 동일함을 보장하는 격리 수준

    MYSQL에서는 이 격리 수준을 default 기본으로 사용한다

    최초에 SELECT를 실행 할때 스냅샷을 만들고 

    이후에 스냅샷에 SELECT를 실행함으로써 다른 트랜잭션에 데이터가 변경 되더라도 조회에 대해 같은 결과를 보장한다

     

    예시)

    1. 읽기 트랜잭션 T1이 amount을 조회  amount = 1000 (스냅샷 생성)
    2. 쓰기 트랜잭션인 T2가 amount를 3000으로 변경하고 커밋한다
    3. T1이 amount를 다시 조회한다 amount = 1000  -> 스냅샷 으로 인해 처음 조회한 값과 동일한 결과를 리턴 (Non-Repeatable Read 해결)

     

    이 격리 수준에서는 Phantom Read 문제가 발생할 수 있다

     

    예시)

    1. 읽기 트랜잭션 T1이 amount의 전체 데이터를 읽는다 (id =1 , amount 1000) 으로 1개가 조회되었다
    2. 쓰기 트랜잭션 T2가 데이터를 삽입한다
    id amount
    1 1000
    2 2000

     

    3. 읽기 트랜잭션 T1이 데이터를 읽는다 위 표처럼 2개가 조회가 된다 -> 이전 조회시에 없었던 데이터가 조회되는 Phantom Read 발생

     

     

    이러한 Phantom Read는 트랜잭션 격리 수준을 Serializable 로 격상함으로써 해결할 수 있다

     

     

     

     

    Serializable(Level 3)

     

    트랜잭션의 읽기 작업 시에도 공유락을 획득하게 함으로써 동시에 다른 트랜잭션이 같은 데이터에 접근 할 수 없도록 하는 격리 레벨

    읽기 트랜잭션이 데이터를 사용하는 동시에 다른 트랜잭션이 INSERT문을 수행할 수 없게 되므로 Phantom Read 문제를 해결

     

    예시)

    1. 읽기 트랜잭션 T1이 amount의 전체 데이터를 읽는다 (id =1 , amount 1000) 으로 1개가 조회되었다
    2. 쓰기 트랜잭션 T2가 데이터를 삽입하려고 하지만 데이터에 접근이 불가능하다 -> Phantom Read 문제 해결

     

    이 격리 수준은 제한이 가장 심해서 데이터의 동시성이 가장 낮다 

    따라서 필요성을 검증하고 사용하는 편이 좋다고한다

     

     

     

    마무리

     

    트랜잭션 격리 수준은 여러 트랜잭션이 같은 데이터나 테이블에 접근하여 생기는 문제들을 해결하기 위해 트랜잭션간 조회할 수 있는 데이터의 범위를 결정하는 것이다

     

    격리 수준을 적절하게 조절 하면서 트랜잭션 동시 실행 문제를 해결할수 있고 격리 수준을 높임으로써 얻는 데이터 일관성과 동시성은 반비례하기 때문에 필요성을 따져 적절하게 쓰이는 것이 중요하다

Designed by Tistory.