본문 바로가기
Today I Learned 2024. 12. 12.

(24.12.12) 관계형 DB의 격리수준

 

채용 공고를 보거나 RDB를 충분히 다룰 수 있다는 있는 역량을 보는 것과 동시에,

Spring Framework 에서의 JPA를 활용하면서, Transaction 전파 전략(Propagation)  설정하는 선에서 Transaction 을 다루고자 했다.

 

하지만, SQL을 활용해서 DB 내에서 Transaction간 격리수준을 설정하는 것만으로 Session 별 또는 Global로 Transaction간 읽기 쓰기에 대한 동시성 제어가 가능할 수 있기 때문에, 

 

Spring 단이 아닌 DB 단에서 격리 수준을 다루기 위해 찾아보고 정리를 했다.

 


관계형 DB의 격리수준

DB의 격리 수준

트랜잭션 간 동시성 제어를 위한 독립성 보장하는 설정

  • 여러 트랜잭션이 동시에 실행될 때 서로의 작업에 간섭하지 않도록 조정
  • 데이터의 일관성과 무결성을 유지 → 경쟁 상태를 최소화
    • 일관성 Independence
      • 논리적 구조와 응용프로그램, 물리적 구조(저장구조)가 서로 변경되더라도 영향을 주지 않는
    • 무결성 Integrity
      • 데이터의 정확성 + 일관성을 보장, DB에 저장된 데이터가 정확, 일관된 유효한 상태인것

중간 상태 데이터를 볼 수 있도록 정의 하는 설정

  • 각 트랜잭션이 실행 중에 다른 트랜잭션이 수행한 변경 사항 (데이터)을 볼 수 있는지를 결정
  • DB 내 트랜잭션 간의 데이터 공유 범위를 제어
    • 트랜잭션 간 영향을 준다는 의미 X

주요 격리 수준

-- 전체(글로벌) 격리 수준 설정
SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITED(아래 격리수준);
-- 세션 격리 수준 설정
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITED(아래 격리수준);

-- 현재 글로벌 격리 수준 확인
SELECT @@global.transaction_isolation;
-- 현재 세션 격리 수준 확인
SELECT @@transaction_isolation;

READ UNCOMMITED

  • 트랜잭션이 커밋되지 않은 데이터를 다른 트랜잭션이 읽을 수 있는 가장 낮은 격리 수준
    • Dirty Read 발생 가능
      • 아직 커밋되지 않은 데이터를 읽음 →데이터의 무결성이 깨질 수 있음
  • 높은 동시성을 제공하지만 데이터 무결성 보장 불가 = 짧게 정리해서 안전하고 신뢰할만한 데이터가 아니라는 점
  • 주로 테스트 또는 성능이 중요한 특정 작업에서 사용

READ COMMITED

  • 트랜잭션이 커밋된 데이터만 다른 트랜잭션이 읽을 수 있는 격리 수준
    • Non-Repeatable Read 발생 가능
      • 동일 트랜잭션 내에서 같은 데이터를 여러 번 조회 시, 다른 결과가 반환될 가능성
  • Dirty Read는 방지
  • 대부분의 DBMS(Oracle, SQL Server)에서 기본으로 사용하는 격리 수준
  • 성능과 데이터 무결성간 균형이 적절하여 일반적으로 많이 사용
    • 흔히 아는 그 격리 수준

REPEATABLE READ

  • 트랜잭션 시작 후 동일 데이터를 여러 번 읽어도 항상 같은 결과를 반환하는 격리 수준
    • 데이터 스냅샷을 보장해서 그 스냅샷에서 데이터를 계속 가져오는 형태
    • Phantom Read 발생 가능
      • 동일한 조건으로 데이터를 조회 시, 이전에는 없던 새로운 데이터가 나타나는 문제
  • Non-Repeatable Read, Dirty Read도 방지
  • MySQL에서는 기본 격리 수준으로 사용

SERIALIZABLE

  • 모든 트랜잭션을 순차적으로 실행하여 동시성 문제를 완전히 방지하는 가장 높은 격리 수준
    • autocommit이 안되어있는 이상, 다른 트랜잭션에서도 잠금이 걸린 상태
    • → Deadlock 걸릴 확률
  • Phantom Read, Non-Repeatable Read, Dirty Read 모두 방지
  • 트랜잭션 간 충돌을 완전히 차단하기 때문에 데이터 무결성 최상으로 보장
  • 동시성 처리 능력이 크게 저하되어 성능 문제가 발생할 수 있음
  • 동시 트랜잭션 수가 적고 데이터 정확성이 매우 중요한 환경에서 사용
격리 수준 특징 발생 가능 문제 주로 사용되는 환경
READ UNCOMMITTED 트랜잭션이 커밋되지 않은 데이터를 읽을 수 있는 가장 낮은 격리 수준 Dirty Read

커밋되지 않은 데이터를 읽음
테스트 또는 성능이 중요한 특정 작업
READ COMMITTED 커밋된 데이터만 읽을 수 있는 격리 수준 Non-Repeatable Read

동일 데이터를 여러 번 조회 시 다른 결과 가능
대부분 DBMS 기본 격리 수준성능과 무결성 균형
REPEATABLE READ 트랜잭션 시작 후 동일 데이터를 여러 번 읽어도 항상 같은 결과를 반환 Phantom Read

조회 시 새로운 데이터가 나타남
MySQL 기본 격리 수준트랜잭션 내 데이터 일관성 보장
SERIALIZABLE 모든 트랜잭션을 순차적으로 실행하여 동시성 문제를 방지 - 데이터 정확성이 중요한 환경동시 트랜잭션 수가 적을 때

Phantom Read 방지 매커니즘

  • 대부분의 애플리케이션에서 요구하는 수준의 데이터 일관성을 제공
  • SERIALIZABLE의 성능 이슈에 비해 균형잡혀있기 때문에 MySQL에서 채택

갭 잠금 (Gap Lock)

  • 인덱스에서 레코드 간의 간격(Gap)을 잠그는 방식
    • WHERE id > 10 AND id < 20 조건에서 (10, 20) 사이의 간격에 대해 잠금이 설정 하는 방식
    • 단, 데이터의 직접적인 값을 수정하는 것이 아닌 그 인덱스의 순서에 관여된 삽입이나 인덱스 이동이 제한되는 것
      • id를 변경 하는 등
  • 트랜잭션이 실행 중인 범위에 다른 트랜잭션이 새로운 레코드를 삽입할 수 없도록 보호
  • 인덱스(따로 인덱스 테이블이 아닌 id 등이 기준)를 통한 검색 시 적용, 기존 데이터의 변경을 막지 않고 간격에 새로운 데이터 삽입을 막음

넥스트 키 락 (Next-Key Lock)

  • 레코드와 그 레코드 다음 위치의 간격을 동시에 잠그는 방식
    • 순서는 데이터의 id 기준 unique 값을 기본, 다른 인덱스가 기준이 된다면 그 인덱스를 기준으로 진행
    • name을 기준으로 한다면 알파벳 순서 등으로 기준이 정해지는 방식
  • 레코드에 대한 수정 및 삽입을 동시에 방지
  • 갭 잠금과 동일하게 새로운 데이터 삽입을 방지 + 데이터 자체의 수정도 막음
  • WHERE id = 10에서 해당 레코드와 그 다음 레코드 간의 간격을 잠가, 다른 트랜잭션이 해당 위치에 삽입 또는 수정할 수 없도록 하는 방식

다음은 각각의 상황을 SQL로 어떠헥 다룰 수 있을 건지 간단하게 적으면서 확인을 하고,

트랜잭션간 WRITE READ 경합 상황 등을 가정해서 어떻게 이뤄질 수 있는지 정리를 할 것