[DB] 트랜잭션 고립 수준

2023. 12. 21. 01:35CS/DataBase

 

트랜잭션 동시 실행 문제

 

지금까지 설명한 락은 두 트랜잭션이 (쓰기, 쓰기)인 상황을 해결하기 위한 것이다. 두 개의 트랜잭션에서 트랜잭션 1은 읽기 작업을 하고 트랜잭션 2는 쓰기 작업을 한다. 락을 사용하여 두 트랜잭션을 동시에 실행시킬 수 있다. 그렇게 되면 두 트랜잭션의 동시 진행 정도를 과도하게 막기 때문이다. 동시성을 높이기 위해서는 좀 더 완화된 방법을 사용할 필요가 있다.

 

트랜잭션 동시 실행 문제

 

트랜잭션은 1은 읽기만 하기 때문에 갱신손실 같은 심각한 문제가 발생하지 않는다. 그러나 트랜잭션 1에서 오손 읽기(dirty read) 문제, 반복불가능 읽기 문제, 유령 데이터 읽기 문제 등이 발생할 수 있다. 읽기만 하는 트랜잭션이 쓰기 트랜잭션에서 작업한 중간 데이터를 읽기 때문에 발생하는 문제들이다.

 

오손 읽기 (dirty read) 

오손 읽기는 읽기 작업을 하는 트랜잭션 1이 쓰기 작업을 하는 트랜잭션 2가 작업하는 중간 데이터를 읽기 때문에 생기는 문제다. 작업 중인 트랜잭션 2가 어떤 이유로 작업을 철회(ROLLBACK)할 경우 트랜잭션 1은 무효가 된 데이터를 읽게 되고 잘못된 결과를 도출한다. 이 현상을 오손 읽기라고 한다.

 

작업 설명 : 두 트랜잭션을 동시에 실행

트랜잭션 T1, T2가 동시에 실행된다. T1은 읽기만 하고 T2는 쓰기를 한다. T1은 T2가 변경한 데이터를 읽어와 작업하는데, T2가 작업 중 철회를 하게 되었다.

 

문제 발생 : 오손 읽기

T2가 변경한 데이터를 T1이 읽은 후 어떤 원인으로 인하여 T2가 스스로 철회를 하게 되었다. 철회를 하면 T2의 작업은 없던 일이 된다. T1은 T2가 정상적으로 종료하지 않은 상태에서 변경한 데이터를 보고 작업을 하게 된 것이다. 트랜잭션 T2가 홍길동의 나이를 30에서 21로 변경한 후 철회하여 트랜잭션 T1에게 오류를 발생시킨 상황이다.

 

 

반복불가능 읽기 : 트랜잭션 중간에 다른 트랜잭션이 변경한 데이터를 읽으면서 발생하는 현상

반복불가능 읽기는 트랜잭션이 1이 데이터를 읽고 트랜잭션 2가 데이터를 쓰고(갱신, UPDATE), 트랜잭션 1이 다시 한 번 데이터를 읽을 때 생기는 문제이다. 즉 트랜잭션 1이 읽기 작업을 다시 한번 반복할 경우 이전의 결과가 반복되지 않는 현상을 반복불가능 읽기라고 한다.

 

작업 설명 : 두 트랜잭션을 동시에 실행

트랜잭션 T1, T2가 동시에 실행된다. T1은 읽기만 하고 T2는 쓰기(갱신, UPDATE)를 한다. T1이 데이터를 읽고 작업을 한 후, T2가 변경한 데이터를 다시 한 번 읽어와 작업을 한다.

 

문제 발생 : 반복불가능 읽기

T1이 데이터를 읽고 작업하던 중 T2가 데이터를 변경하였다. T1은 변경한 데이터를 보고 다시 한 번 작업을 하였다. 오손 읽기와 달리 이번에는 T2가 정상적으로 종료하여 COMMITE을 했기 때문에 틀린 데이터는 아니다. 그런데 T1 입장에서는 같은 SQL문이 다른 결과를 도출한다.

 

 

 

유령데이터 읽기 : 트랜잭션 중간에 다른 트랜잭션이 삽입한 데이터를 읽으면서 발생하는 현상

유령데이터 읽기는 트랜잭션 1이 데이터를 읽고 트랜잭션 2가 데이터를 쓰고(삽입, INSERT), 트랜잭션 1이 다시 한번 데이터를 읽을 때 생기는 문제이다. 트랜잭션 1이 읽기 작업을 다시 한번 반복할 경우 이전에 없던 데이터가(유령 데이터)가 나타나는 현상을 유령 데이터 읽기라고 한다.

 

작업 설명 : 두 트랜잭션을 동시에 실행

트랜잭션 T1은 읽기만 하고 T2는 쓰기(삽입, INSERT)를 한다. T1은 데이터를 읽고 작업을 한 후, 그 사이에 T2가 변경한 데이터를 다시 한 번 읽어와 작업을 한다.

 

문제 발생 : 유령데이터 읽기 

이번에는 T1이 T2가 새로운 데이터를 삽입한 사실을 모르고 작업을 한다. T2가 COMMIT을 했기 때문에 틀린 데이터는 아니다. 그러나 T1 입장에서는 새로운 데이터가 반영되어 반복불가능 읽기와 마찬가지로 같은 SQL 문이 다른 결과를 도출한다. 유령데이터 읽기는 반복불가능 읽기와 비슷하지만 없던 데이터가 삽입되기 때문에 다르게 구분한다.

 

MySQL에서는 유령데이터 읽기가 발생하지 않는다. MySQL의 REPEATABLE READ는 트랜잭션이 처음 데이터를 읽어올 때 SNAPSHOT을 구축하여 자료를 가져오면 그에 따라 다른 세션의 자료가 변경되더라도 동일한 결과를 보여주게 된다.

 

트랜잭션 고립 수준 명령어

 

  • READ UNCOMMITTED(Level=0)
    • 고립 수준이 가장 낮은 명령어로, 자신의 데이터에 아무런 공유락을 걸지 않는다(배타락은 갱신손실 문제 때문에 걸어야 한다.) .
    • 다른 트랜잭션에 공유락과 배타락이 걸린 데이터를 대기하지 않고 읽는다.
    • 다른 트랜잭션이 COMMIT 하지 않은 데이터도 읽을 수 있다. 때문에 오손 페이지의 데이터를 읽게 된다. 이 명령어는 SELECT 질의의 대상이 되는 테이블에 대해서 락을 설정하지 않은 것과 같다
  • READ COMMITTED (Level=1)
    • 오손 페이지의 참조를 피하기 위해 자신의 데이터를 읽는 동안 공유락을 걸지만 트랜잭션이 끝나기 전에라도 해지가능하다.
    • 다른 트랜잭션 데이터는 락 호환성 규칙에 따라 진행한다.
  • REPEATEABLE READ (Level=2)
    • 자신의 데이터에 설정된 공유락과 배타락을 트랜잭션이 종료될 때까지 유지하여 다른 트랜잭션이 자신의 데이터를 갱신할 수 없게 한다.
    • 다른 트랜잭션 데이터는 락 호환성 규칙에 따라 진행한다. 다른 고립화 수준에 비해 데이터의 동시성이 낮아 특별한 상황이 아니라면 사용하지 않는 것이 좋다.
  • SERIALIZABLE (Level=3)
    • 고립 수준이 가장 높은 명령어로, 실행 중인 트랜잭션은 다른 트랜잭션으로부터 완벽하게 분리된다.
    • 데이터 집합에 범위를 지어 잠금을 설정할 수 있기 때문에 다른 사용자가 데이터를 변경하려 할 때 트랜잭션을 완벽하게 분리할 수 있다.
    • 네 가지 고립화 수준 중 제한이 가장 심하고 데이터의 동시성도 낮다. 
    • SELECT 질의의 대상이 되는 테이블에 미리 배타락을 설정한 것과 같은 효과를 낸다.

 

 

'CS > DataBase' 카테고리의 다른 글

[DB] JOIN 정리  (0) 2023.12.30
[DB] 회복  (0) 2023.12.21
[DB] 동시성 제어  (0) 2023.12.20
[DB] 트랜잭션  (0) 2023.12.20
[DB] 정규화  (0) 2023.12.19