트랜잭션 격리 수준 (Transaction Isolation Level)
한눈에 보기
격리 수준은 동시 실행되는 트랜잭션이 서로의 변경을 어디까지 볼 수 있는지 정한 규칙이다. 네 단계별 이상 현상 비교, MVCC와 갭 락 구현, 실무 선택 기준을 정리한다.
최종 업데이트 2026.09.17
트랜잭션 격리 수준(Transaction Isolation Level)은 동시에 실행되는 여러 트랜잭션이 서로의 변경 내용을 어디까지 볼 수 있는지를 단계적으로 정의한 규칙이다. SQL 표준은 READ UNCOMMITTED, READ COMMITTED, REPEATABLE READ, SERIALIZABLE의 네 단계를 정의하며, 수준이 높을수록 데이터 정합성은 좋아지지만 동시 처리 성능은 낮아지는 트레이드오프가 있다.
격리 수준이 필요한 이유
트랜잭션의 격리성(Isolation)을 완벽하게 지키려면 모든 트랜잭션을 한 줄로 세워 순차 실행해야 하지만, 그러면 동시에 한 명의 사용자만 처리할 수 있는 것과 다름없어 성능이 무너진다. 그래서 데이터베이스는 격리를 어느 정도 느슨하게 풀어 동시성을 확보하는 대신, 어떤 부작용까지 허용할지를 개발자가 선택하도록 단계화했다. 이 부작용이 바로 더티 리드, 반복 불가능 읽기, 팬텀 리드다.
격리가 느슨할 때 생기는 세 가지 현상
더티 리드(Dirty Read)
다른 트랜잭션이 아직 커밋하지 않은 변경 값을 읽는 현상이다. 그 트랜잭션이 롤백되면 존재한 적 없는 데이터를 읽고 판단한 셈이 된다.
반복 불가능 읽기(Non-Repeatable Read)
한 트랜잭션 안에서 같은 행을 두 번 조회했는데, 그 사이에 다른 트랜잭션이 값을 수정하고 커밋해서 두 결과가 달라지는 현상이다.
팬텀 리드(Phantom Read)
같은 조건으로 범위를 두 번 조회했는데, 그 사이에 다른 트랜잭션이 조건에 맞는 행을 삽입하거나 삭제해서 결과 행의 집합이 달라지는 현상이다. 행 하나의 값이 바뀌는 반복 불가능 읽기와 달리, 없던 행이 나타나거나 있던 행이 사라진다는 점이 다르다.
네 가지 격리 수준
| 격리 수준 | 더티 리드 | 반복 불가능 읽기 | 팬텀 리드 |
|---|---|---|---|
| READ UNCOMMITTED | 발생 | 발생 | 발생 |
| READ COMMITTED | 방지 | 발생 | 발생 |
| REPEATABLE READ | 방지 | 방지 | 발생 가능(표준 기준) |
| SERIALIZABLE | 방지 | 방지 | 방지 |
READ UNCOMMITTED는 커밋되지 않은 데이터까지 읽는 가장 낮은 수준으로, 정합성 문제 때문에 실무에서 거의 쓰이지 않는다. READ COMMITTED는 커밋된 데이터만 읽는 수준으로 오라클(Oracle)과 PostgreSQL의 기본값이다. REPEATABLE READ는 트랜잭션이 시작된 시점의 일관된 스냅숏을 기준으로 읽어 같은 조회 결과를 보장하는 수준으로 MySQL InnoDB의 기본값이다. SERIALIZABLE은 트랜잭션들을 순차 실행한 것과 같은 결과를 보장하는 가장 엄격한 수준이지만, 읽기에도 잠금이 관여해 동시성이 크게 떨어지고 교착 상태와 직렬화 실패가 늘어난다.
-- 현재 세션의 격리 수준 변경 (MySQL)
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
-- 격리 수준 확인
SELECT @@transaction_isolation;
MVCC와 잠금: 격리 수준의 구현
최신 데이터베이스는 격리 수준을 주로 다중 버전 동시성 제어(MVCC, Multi-Version Concurrency Control)로 구현한다. 데이터를 수정할 때 이전 버전을 언두(Undo) 영역에 남겨 두고, 읽는 트랜잭션은 자신의 기준 시점에 맞는 버전을 찾아 읽는 방식이다. 덕분에 읽기 작업이 쓰기 작업을 기다리지 않아 잠금 기반 방식보다 동시성이 훨씬 좋다. READ COMMITTED는 문장 단위로, REPEATABLE READ는 트랜잭션 단위로 스냅숏 기준 시점을 잡는다는 것이 두 수준의 본질적 차이다.
MySQL InnoDB의 REPEATABLE READ는 표준상 허용되는 팬텀 리드도 상당 부분 막는다. 일반 조회는 스냅숏 읽기로 일관성을 유지하고, SELECT ... FOR UPDATE 같은 잠금 읽기에는 조회한 행뿐 아니라 행 사이의 간격까지 잠그는 갭 락(Gap Lock)과 넥스트 키 락(Next-Key Lock)을 사용해 새 행의 삽입 자체를 차단하기 때문이다. 다만 스냅숏 읽기와 쓰기가 섞이는 경우 등 일부 상황에서는 여전히 예상 밖의 결과가 나올 수 있어, 잔액 차감 같은 정합성이 중요한 갱신에는 잠금 읽기나 원자적 UPDATE를 명시적으로 사용해야 한다.
실무 선택 기준
격리 수준은 서비스 전체가 아니라 요구 사항 단위로 판단하는 것이 좋다. 일반적인 웹 서비스 조회와 갱신은 READ COMMITTED나 REPEATABLE READ로 충분하며, 실제로 대부분의 서비스가 데이터베이스 기본값을 그대로 사용한다. 통계 집계처럼 한 트랜잭션 안에서 일관된 기준 시점이 필요하면 REPEATABLE READ가 유리하고, 재고 차감이나 중복 예약 방지처럼 경합이 곧 장애가 되는 로직은 격리 수준을 올리기보다 잠금 읽기, 유니크 제약, 원자적 갱신 쿼리로 지점 방어하는 편이 성능과 정합성을 모두 챙기는 방법이다. SERIALIZABLE은 그 비용을 감수할 명확한 이유가 있을 때만 제한적으로 사용한다.
면접에서 이렇게 물어본다
- 네 가지 격리 수준과 각 수준에서 발생 가능한 이상 현상을 표로 그리듯 설명해 보라.
- 반복 불가능 읽기와 팬텀 리드의 차이는 무엇인가.
- MVCC가 무엇이고, 잠금 기반 동시성 제어와 비교해 어떤 장점이 있는가.
- MySQL InnoDB의 REPEATABLE READ가 팬텀 리드를 막는 방법을 갭 락과 함께 설명해 보라.
- 재고 차감 로직의 동시성 문제를 격리 수준만으로 해결할 수 있는가, 다른 방법은 무엇인가.
데이터베이스에서 같이 읽기
- 이상 현상 (Anomaly)이상 현상은 테이블 설계가 잘못되어 삽입, 갱신, 삭제 과정에서 데이터 불일치나 손실이 생기는 현상이다. 삽입, 갱신, 삭제 이상의 세 종류와 원인인 함수 종속, 해결책인 정규화까지 예시와 함께 정리한다.
- 데이터베이스 커넥션 풀 (Database Connection Pool)데이터베이스 연결을 미리 만들어 재사용하는 커넥션 풀의 동작 원리와 필요성을 다룬다. HikariCP 설정, 풀 크기 계산, 타임아웃과 고갈 문제를 실무 관점에서 정리했다.
- 인덱스 (Index)인덱스는 컬럼 값과 저장 위치를 별도 자료구조로 정리해 검색 속도를 높이는 장치다. B+Tree 동작 원리, 클러스터드와 논클러스터드 비교, 복합 인덱스와 커버링 인덱스, 설계 시 주의점을 다룬다.
- 데이터베이스 레플리케이션 (Database Replication)원본 데이터베이스의 변경을 레플리카에 복제해 읽기 부하와 장애를 분산하는 구조를 다룬다. 동기와 비동기 복제, 복제 지연, 읽기 일관성과 장애 전환을 정리했다.
이 개념, 내 코드에서는 어떻게 물어볼까요
데브핏(DevFit)에 채용공고 URL을 붙여 넣고 레포지토리를 연결하면, 내가 쓴 커밋에서 예상 질문과 어필 포인트를 만듭니다. 하루 10회까지 무료입니다. 합불 판정이나 지원자 랭킹은 만들지 않고, 최종 판단은 사람이 합니다.
공고 넣고 시작하기