MVCC

MVCC (Multi-Version Concurrency Control)

  • MVCC(Multi-Version Concurrency Control) 는 데이터베이스에서 동시성을 높이고 트랜잭션 간의 충돌을 줄이기 위해 사용되는 기법.
  • PostgreSQL과 MySQL(InnoDB)은 각각 다른 방식으로 MVCC를 구현하여, 트랜잭션이 락을 걸지 않고도 데이터를 안전하게 읽을 수 있도록 보장한다.

PostgreSQL의 MVCC (Tuple Versioning)

PostgreSQL은 Tuple Versioning 방식으로 MVCC를 구현.

PostgreSQL MVCC 동작 방식

  1. 트랜잭션이 시작될 때, 특정 시점(Snapshot)의 데이터를 읽음
    • 다른 트랜잭션이 데이터를 변경하더라도, 현재 트랜잭션에서는 변경 전 데이터가 유지됨.
  2. 각 행(Row, Tuple)에 xmin, xmax 필드(트랜잭션 ID)를 유지
    • xmin: 해당 데이터를 생성한 트랜잭션 ID
    • xmax: 해당 데이터를 삭제 또는 수정한 트랜잭션 ID
  3. DELETE 및 UPDATE 시, 기존 데이터를 즉시 삭제하지 않고 새로운 버전을 생성
    • UPDATE는 내부적으로 DELETE + INSERT 방식으로 처리됨.
    • 따라서 기존 데이터는 유지되며, 새로운 트랜잭션은 가장 최신 데이터를 확인함.
  4. 커밋되지 않은 트랜잭션이 생성한 데이터를 다른 트랜잭션에서는 볼 수 없음
    • SELECT 시 해당 트랜잭션의 Snapshot을 기준으로 유효한 튜플만 조회함.
  5. 오래된 데이터(불필요한 튜플)는 Autovacuum 프로세스를 통해 정리됨
    • PostgreSQL에서는 오래된 튜플(더 이상 사용되지 않는 데이터)을 Autovacuum이 주기적으로 정리하여 스토리지를 최적화함.

PostgreSQL MVCC 예제

-- 트랜잭션 1 시작
BEGIN;
UPDATE users SET name = 'Alice' WHERE id = 1; -- 기존 행을 삭제하고 새 행을 삽입
-- 트랜잭션이 아직 커밋되지 않음

-- 트랜잭션 2에서 동일한 데이터를 조회
SELECT * FROM users WHERE id = 1;
-- 트랜잭션 1이 커밋되지 않았다면 기존 데이터가 유지됨
  • PostgreSQL에서는 트랜잭션 ID(xmin, xmax)를 기반으로 다른 트랜잭션에서 볼 수 있는 데이터를 결정.
  • 즉, 트랜잭션이 변경한 데이터를 다른 트랜잭션에서 즉시 볼 수 없으며, 변경 전 데이터를 유지하는 방식.

MySQL(InnoDB)의 MVCC (Undo Log 기반)

MySQL의 InnoDB는 Undo Log 기반으로 MVCC를 구현.

MySQL MVCC 동작 방식

  1. 트랜잭션이 시작될 때, 특정 시점(Snapshot)의 데이터를 읽음
    • 다른 트랜잭션이 데이터를 변경하더라도, 현재 트랜잭션에서는 변경 전 데이터를 유지.
  2. Undo Log를 사용하여 과거 데이터를 관리
    • 변경 전 데이터를 Undo Log에 저장해 두고, 특정 트랜잭션이 이전 버전 데이터를 필요로 하면 Undo Log를 조회하여 제공.
  3. DELETE 및 UPDATE 시, 기존 데이터를 즉시 삭제하지 않고 Undo Log에 저장
    • UPDATE는 내부적으로 DELETE + INSERT 방식으로 처리되며, Undo Log를 활용하여 과거 버전을 유지.
  4. SELECT 시 Undo Log를 참조하여 트랜잭션 격리 수준을 유지
    • Read Committed에서는 커밋된 최신 데이터를 읽고,→ Repeatable Read에서는 트랜잭션이 시작될 당시의 데이터를 유지함.
  5. Purge Thread가 오래된 Undo Log를 정리
    • MySQL은 PostgreSQL의 Autovacuum과 달리, Purge Thread가 불필요한 Undo Log를 제거함.

MySQL MVCC 예제

-- 트랜잭션 1 시작
START TRANSACTION;
UPDATE users SET name = 'Bob' WHERE id = 1; -- 기존 데이터를 변경
-- 트랜잭션이 아직 커밋되지 않음

-- 트랜잭션 2에서 동일한 데이터를 조회
SELECT * FROM users WHERE id = 1;
-- MySQL의 MVCC는 Undo Log를 활용하여 변경 전 데이터를 제공
  • MySQL에서는 Undo Log를 사용하여 트랜잭션이 변경한 데이터를 다른 트랜잭션에서 즉시 볼 수 없도록 보장.
  • 즉, Undo Log를 조회하여 “트랜잭션 시작 시점의 데이터”를 유지하는 방식.

PostgreSQL vs MySQL(InnoDB) MVCC 비교

특징 PostgreSQL MySQL (InnoDB)
MVCC 방식 Tuple Versioning (각 행에 여러 버전 저장) Undo Log 기반 (과거 데이터를 Undo Log에 저장)
데이터 삭제 방식 DELETE 및 UPDATE 시, 기존 데이터를 유지하고 새 버전 생성 Undo Log에 기존 데이터 저장 후 삭제
Garbage Collection Autovacuum 프로세스가 오래된 데이터를 정리 Purge Thread가 불필요한 Undo Log 정리
트랜잭션 시작 시 데이터 읽기 트랜잭션 ID(xmin, xmax)를 기반으로 유효한 데이터 결정 Undo Log를 참조하여 트랜잭션 시작 당시 데이터를 유지
SELECT 락 사용 여부 SELECT 시 락을 걸지 않음 SELECT 시 락을 걸지 않음
Read Committed 격리 수준 최신 커밋된 데이터만 읽음 최신 커밋된 데이터만 읽음
Repeatable Read 격리 수준 트랜잭션 시작 시점의 데이터를 유지 Undo Log를 사용하여 트랜잭션 시작 시점의 데이터를 제공

정리

  1. PostgreSQL의 MVCC는 Tuple Versioning 방식을 사용
    • 각 행(Row)에 트랜잭션 ID(xmin, xmax)를 저장하여 버전 관리
    • Autovacuum이 오래된 데이터(Tuple)를 정리
    • 장점: Undo Log가 필요 없고, 읽기 트랜잭션이 가볍다.
    • 단점: 업데이트가 많으면 오래된 Tuple이 쌓여 성능 저하 가능.
  2. MySQL InnoDB의 MVCC는 Undo Log 기반으로 동작
    • 변경 전 데이터를 Undo Log에 저장하여 과거 데이터를 제공
    • Purge Thread가 불필요한 Undo Log를 제거
    • 장점: Undo Log를 통해 과거 데이터를 관리하여 불필요한 데이터 유지 최소화.
    • 단점: Undo Log가 쌓이면 Purge Thread 부담 증가, 성능 저하 가능.

Categories:

Updated:

Comments