데이터 엔지니어링

[데이터 중심 애플리케이션 설계] 7장 트랜잭션 - 직렬성

* 이 글은 [데이터 중심 애플리케이션 설계]를 공부하며 기록을 남긴 것입니다.


직렬성

  • 여러 트랜잭션이 병렬로 실행되더라도 직렬로 실행되는 것과 최종적으로는 같도록 보장하는 것
  • 완벽한 격리 수준인 것 같지만 완벽히 구현하기 매우 어렵다.
  • 단일 노드 DB를 기준으로 봄.
  • 구현 방법 3가지

 

1. 순차적으로 실행하기

  • 한 번에 한 트랜잭션만 직렬로 단일 스레드에서 실행하는 방법
    • 메모리에 더 많은 데이터를 담을 수 있고, 대부분의 OLTP 트랜잭션은 짧기 때문에 가능해짐
  • 잠금으로 발생하는 오버헤드를 줄일 수 있지만, 처리량이 CPU 하나 수준으로 제한됨 → 다른 형태로 구조화

 

스토어드 프로시저

  • 단일 스레드에서 실행하기 위해서는 트랜잭션 코드 전체를 스토어드 프로시저 형으로 변환하여 실행
  • I/O 대기, 오버헤드를 회피하여 단일 스레드 대비 좋은 처리량

파티셔닝

  • 여러 CPU와 노드로 확장하기 위해 파티셔닝 사용
  • 여러 파티션을 코디네이션 해야 하고(오버헤드), 스토어드 프로시저는 직렬성 보장을 위해 모든 파티션에 걸쳐 잠금을 획득해야 한다.

→ 결국 작고 빠른 트랜잭션, 필요한 데이터셋이 메모리에 적재될 수 있는 경우, 쓰기 처리량이 단일 CPU로도 충분한 경우에만 이 방법을 사용할 수 있다. 위 조건을 만족하면 직렬성 격리를 획득하는 실용적인 방법!

 

2. 2단계 잠금(2-phase locking)

  • 스냅숏 격리와 비슷하지만, 쓰기 트랜지션은 읽기 트랜지션도 제한함으로써 직렬성을 보장한다.
  • 공유 모드(여러 트랜잭션이 잠금 획득 가능)와 독점 모드(한 트랜잭션만 잠금 획득 가능)로 잠금 구현
  • 교착 상태 가능성 ↑
  • 잠금으로 인한 오버헤드와 동시성이 줄어드는 문제로 성능이 크게 나빠짐
    • 한 트랜잭션은 다른 트랜잭션이 완료될 때 까지 기다려야 함
    • 한 트랜잭션이 검색 질의 결과를 바궈버리는 팬텀 문제를 막아야 함
    • 성능 문제로 요즘은 사용을 피하는 경우가 많다

 

서술 잠금

  • 검색 조건에 만족하는 모든 객체를 잠금하는 것
  • 나중에 추가되는 데이터에도 적용이 가능하다.
  • 진행중인 트랜잭션이 획득한 잠금이 많으면, 조건에 만족하는 객체를 찾는 데에 오래걸린다.

색인 범위 잠금

조건에 만족하는 객체를 찾는 데에 걸리는 시간을 줄이기 위해, 조건을 조금 더 넓은 범위로 근사시킨다.

ex) 10개 회의실이 있을 때, 1시~2시에 3번 방을 예약하기 위한 잠금은 1~2시에 모든 방을 잠그거나, 모든 시간대에 대해 3번 방을 잠그는 것으로 범위를 넓힐 수 있다. 다른 트랜잭션이 범위가 겹치는 데이터의 변경을 원하면, 잠금이 풀리기까지 기다려야 한다.

  • 서술 잠금보다 많은 데이터를 잠궈야 할 수 있지만 오버헤드가 훨씬 낮다.
  • 팬텀과 쓰기 스큐 문제를 피할 수 있다.

 

3. 직렬성 스냅숏 격리(SSI)