Yomni's TIL Help

MVCC(Multi Version Concurrency Control), 격리수준, Lock, 문제유형

4 mvcc phantom read

MVCC(Multi Version Concurrency Control) : 다중 버전 동시성 제어

InnoDB에서는 하나의 레코드에 대하여 언두로그와 버퍼풀을 이용한 다중 버전의 레코드를 가지고 있으며,
이를 통해 효율적인 동시성 제어를 할 수 있다.

1. 격리수준 (Isolation Level) 개요

  • 격리 수준은 ANSI SQL 표준에 따라 4가지로 분류됩니다.

격리 수준(Isolation Level)

주로 사용하는 락 단위

설명

발생 가능 문제

Read Uncommitted (읽기 미확정)

없음 (락 없이 읽기)

다른 트랜잭션의 미확정 데이터를 읽을 수 있는 가장 낮은 수준의 격리 수준입니다.

Dirty Read(더러운 읽기), Non-Repeatable Read, Phantom Read

Read Committed (읽기 확정)

Row-Level Lock (또는 Page-Level Lock)

다른 트랜잭션이 확정(Commit)한 데이터만 읽을 수 있습니다.

Non-Repeatable Read, Phantom Read

Repeatable Read (반복 가능 읽기)

Row-Level Lock 유지

하나의 트랜잭션에서 같은 데이터를 여러 번 읽더라도 동일한 데이터를 보장받는 격리 수준입니다.

Phantom Read

Serializable (직렬화 가능)

Table-Level Lock 또는 Range Lock (Index Lock)

트랜잭션을 순차적으로 수행하게 하여 가장 높은 수준의 격리를 제공합니다.

성능 저하 (동시성 감소)

1-1. 락 단위에 대한 용어 정리

  • 각 락 단위를 설명하는 주요 용어는 다음과 같다.

락 종류

설명

사용되는 격리 수준

Row-Level Lock

개별 행(row) 에 락을 걸어 다른 트랜잭션이 변경하지 못하게 함

Read Committed, Repeatable Read

Page-Level Lock

한 페이지(기본적으로 8KB 단위) 내의 모든 행을 잠금

일부 DBMS 에서 사용

Table-Level Lock

테이블 전체에 대한 락을 설정하여 모든 행을 보호

Serializable

Range Lock (Key-Range Lock)

인덱스 범위에 대한 락을 설정하여 팬텀 리드 방지

Serializable

1-2. 주요 DBMS 별 격리 수준 기본값

  • 각 DBMS 는 기본적으로 사용하는 격리 수준이 다르다.

DBMS

기본 격리 수준

MySQL(InnoDB)

Repeatable Read

PostgreSQL

Read Committed

Oracle

Read Committed

SQL Server

Read Committed

2. 문제 유형

문제 유형

설명

Dirty Read (더러운 읽기)

다른 트랜잭션이 아직 커밋하지 않은 데이터를 읽는 현상

Non-Repeatable Read (반복 불가능한 읽기)

같은 쿼리를 두 번 실행할 때 결과가 다를 수 있음 (중간에 다른 트랜잭션이 변경)

Phantom Read (팬텀 읽기)

트랜잭션 도중 새로운 행이 추가/삭제되거나 변경되어 결과가 달라지는 현상

2-1. Dirty Read 예제

  • 더러운 읽기 : 오염된 데이터를 읽을 수 있다는 의미로 이해하면 쉬움

-- 트랜잭션 A: 계좌 잔액을 100원 증가 (아직 커밋 안 함) BEGIN TRANSACTION; UPDATE accounts SET balance = balance + 100 WHERE id = 1; -- 트랜잭션 B: 아직 커밋되지 않은 데이터를 읽음 SELECT balance FROM accounts WHERE id = 1; -- Dirty Read 발생 가능 -- 트랜잭션 A 롤백 ROLLBACK;

2-2. Non-Repeatable Read 예제

  • 같은 데이터를 한 트랜잭션에서 두 번 이상 읽을 때 값이 변경되는 경우

-- 트랜잭션 A: 계좌 잔액 조회 BEGIN TRANSACTION; SELECT balance FROM accounts WHERE id = 1; -- 결과: 1000원 -- 트랜잭션 B: 계좌 잔액 변경 후 커밋 UPDATE accounts SET balance = 1100 WHERE id = 1; COMMIT; -- 트랜잭션 A: 다시 같은 계좌 잔액 조회 SELECT balance FROM accounts WHERE id = 1; -- 결과: 1100원 (데이터가 변함)

2-3 Phantom Read 예제

  • 같은 조건의 SELECT 문이 다른 결과를 반환하는 경우

-- 트랜잭션 A: 특정 조건을 만족하는 사용자 수 조회 BEGIN TRANSACTION; SELECT COUNT(*) FROM users WHERE age > 30; -- 결과: 10명 -- 트랜잭션 B: 새로운 사용자를 추가하고 커밋 INSERT INTO users (id, name, age) VALUES (11, 'NewUser', 35); COMMIT; -- 트랜잭션 A: 다시 같은 조건으로 사용자 수 조회 SELECT COUNT(*) FROM users WHERE age > 30; -- 결과: 11명 (팬텀 읽기 발생)

느낀점

MVCC엔 장점만 있고 단점은 없을거라 생각했는데,
격리수준지원하고자 하는 서비스의 방향성에 따라 단점이 될 수도 있다는 것을 알게되었다.

참고

Last modified: 19 February 2025