본문 바로가기
CS

RealMySQL - REAPEATABLE READ

by 준형코딩 2025. 6. 22.

 

REPEATABLE READ란?

 

- REAPEATABLE READ는 MySQL의 InnoDB 스토리지 엔진에서 기본으로 사용되는 격리 수준

- MVCC를 위해 언두 영역에 백업된 이전 데이터를 이용해 동일 트랜잭션 내에서는 동일한 결과를 보여줄 수 있게 보장함


1. 주요 특징

특징설명

 

동일 쿼리 반복 시 결과 일관성 유지 트랜잭션이 시작된 순간의 스냅샷을 기준으로 데이터를 조회한다.
Phantom Read 방지 MySQL(InnoDB)은 Next-Key Locking을 통해 팬텀 리드를 막는다.
Serializable보다 성능이 좋음 완벽한 직렬화(Serializable) 수준보다 성능이 높고 동시성도 괜찮은 편이다.
Read Committed보다 보수적 다른 트랜잭션에서 커밋한 내용도, 트랜잭션 내에서는 보이지 않음.
 

2. 내부 동작 방식

1. 스냅샷 기반 읽기 (MVCC)

  • 트랜잭션이 시작되면 해당 시점의 데이터 스냅샷을 생성하고 이를 기준으로 읽기 작업을 수행함.
  • 이후 다른 트랜잭션에서 변경된 데이터가 커밋되더라도, 현재 트랜잭션에는 보이지 않음.

2. Next-Key Lock

  • InnoDB에서는 팬텀 리드를 방지하기 위해 기존 행 + 범위에 잠금을 건다.
  • 예: SELECT * FROM users WHERE age > 30 FOR UPDATE → age 30~∞ 범위 전체를 잠금.

3. 예시 시나리오

상황

  • 트랜잭션 A와 트랜잭션 B가 동시에 실행 중
  • 테이블: accounts(id, balance)

Step-

-- 트랜잭션 A 시작
START TRANSACTION;
-- A: 사용자 잔고 확인
SELECT balance FROM accounts WHERE id = 1;
-- 결과: 1000원
 
-- 트랜잭션 B 시작
START TRANSACTION;
-- B: 사용자 잔고 차감
UPDATE accounts SET balance = balance - 500 WHERE id = 1; COMMIT;
 
-- 다시 트랜잭션 A에서 같은 쿼리 실행
SELECT balance FROM accounts WHERE id = 1;
-- 결과: 여전히 1000원 (트랜잭션 A가 시작된 시점 기준으로 읽음)
 
-- 트랜잭션 A 커밋 COMMIT;

 

 

4. 예외 상황

사용자 B의 트랜잭션 안에서 SELECT ... FOR UPDATE로 특정 범위의 데이터를 조회한 후, 사용자 A가 그 범위에 해당하는 새로운 데이터를 INSERT하고 COMMIT하면, 사용자 B가 나중에 동일한 SELECT ... FOR UPDATE 쿼리를 다시 실행했을 때 이전에는 없던 유령 데이터가 나타나는 팬텀 리드가 발생할 수 있다. 그 이유는 SELECT ... FOR UPDATE는 일반 SELECT처럼 트랜잭션 시작 시점의 스냅샷(언두 로그)을 참조하는 것이 아니라, 항상 가장 최신 버전의 실제 데이터를 읽어오기 때문이다.