코드몽키
트랜잭션의 격리수준 (Isolation Level) 해체 분석기 본문
대규모 시스템에서 여러 트랜잭션이 동시에 수행될 때, 데이터의 일관성과 성능은 늘 서로 충돌하는 문제라고 할 수 있다. 이때 DB는 트랜잭션의 ACID 중 하나인 isolation을 통해 "얼마나 다른 트랜잭션으로부터 독립적으로 동작할지"를 결정하게 된다.
DBMS에서는 이를 격리 수준(Isolation Level) 로 조정하며, 격리 수준이 높을수록 데이터 일관성(Consistency)은 강해지고, 그만큼 동시성 처리 성능은 떨어지게 된다.
트랜잭션 격리 수준은 격리 수준이 낮은 순서대로 READ UNCOMMITTED, READ COMMITTED, REPEATABLE READ, SERIALIZABLE가 존재한다.
각 격리수준 레벨의 특징과 발생 할 수 있는 문제점을 아래와 같이 상품 재고의 조회와 변경 시나리오를 예시로 들어 설명해 보겠다.
✅ READ UNCOMMITTED (Level 0)
1. 상품 재고 수정 트랜잭션이 시작되어 상품 A의 재고를 10개에서 0개로 변경하고 있다.
2. 동시에 재고 조회 트랜잭션이 실행되어 상품 A의 재고를 조회한다.
3. READ UNCOMMITED에서는 아직 커밋되지 않은 변경 내용도 읽을 수 있기 때문에, 조회 트랜잭션은 재고 0개로 확인된다.
4. 하지만 이후 주문 프로세스에 오류가 발생해 재고 수정 트랜잭션이 ROLLBACK 되면, 실제 재고는 다시 10개로 복구 된다.
5. 결과적으로 조회 트랜젹션은 존재하지 않았던 재고 0개라는 잘못된 데이터를 읽은 것
6. Dirty Read 발생

Dirty Read
커밋되지 않은(uncommitted) 데이터를 다른 트랜잭션이 읽는 현상.
Dirty Read한 데이터를 이용해 다른 작업이 수행 되었다면 데이터의 정합성이 완전이 깨져 논리적 오류가 발생 될 것이다.
READ UNCOMMITTED는 SQL 표준에 정의된 공식 격리 수준이지만, 데이터 정합성이 거의 보장되지 않아 대부분의 RDBMS에서는 실질적으로 사용되지 않는다.
✅ READ COMMITED (Level 1)
1. 상품 재고 수정 트랜잭션이 시작되어 상품 A의 재고를 10개에서 0개로 변경하고 있다.
2. 동시에 재고 조회 트랜잭션이 실행되어 상품 A의 재고를 조회한다.
3. READ COMMITTED에서는 커밋된 데이터만 읽을 수 있기 때문에, 조회 트랜잭션은 재고 10개로 확인된다.
4. 이후 재고 수정 트랜잭션이 커밋되면, 실제 재고는 0개로 변경된다.
5. 조회 트랜잭션이 같은 상품을 다시 조회하면 재고 0 개로 확인된다.
6. 결과적으로 같은 트랜잭션 내에서 반복 조회 시 값이 달라지는 Non-Repeatable Read가 발생 할 수 있다.

Non-Repeatable Read
하나의 트랜잭션 내에서 동일한 데이터를 두 번 조회했을 때, 다른 트랜잭션의 커밋으로 인해 값이 달라지는 현상
Dirty Read와 달리 커밋된 데이터만 읽지만, 트랜잭션이 진행되는 동안 다른 트랜잭션이 값을 바꾸면 같은 데이터를 반복 조회해도 이전과 다른 값이 나타난다.
READ COMMITTED에서는 Dirty Read는 발생하지 않지만, 반복 조회 시 값이 달라질 수 있어 논리적 오류가 발생할 가능성이 있다. 대부분의 RDBMS에서 기본 격리 수준으로 사용되며, 금융이나 회계와 같이 높은 일관성이 필요한 경우에는 REPEATABLE READ 이상을 적용해야 한다.
✅ REPEATABLE READ (Level 2)
1. 상품 재고 수정 트랜잭션이 시작되어 상품 A의 재고를 10개에서 0개로 변경하고 있다.
2. 동시에 재고 조회 트랜잭션이 실행되어 상품 A의 재고를 조회한다.
3. REPEATABLE READ에서는 한 트랜잭션 내에서는 처음 조회한 데이터를 계속 동일하게 읽을 수 있음 조회 트랜잭션
4. 이후 재고 수정 트랜잭션이 커밋되더라도, 같은 조회 트랜잭션이 다시 조회하면 여전히 10개로 확인된다.
5. 다만 트랜잭션 조건에 맞는 신규 데이터가 생긴다면 조회 트랜잭션 내에서 이전 데이터도 row에 포함되서 조회되는 현상이 발생한다.

Phantom Read
같은 조건의 쿼리를 반복 실행했는데, 다른 트랜잭션에서 새로 추가된 행(row)이 결과에 포함되는 현상
트랜잭션의 REPEATABLE READ는 일반적으로“트랜잭션이 시작될 때 형성된 읽기 전용 스냅샷을 끝까지 유지한다”는 개념으로 이해할 수 있다. 즉, 같은 트랜잭션에서 동일한 SELECT를 반복해도 항상 동일한 결과가 보이도록 보장하는 수준이다.
[표준의 정의 vs 실제 구현]
일반적인 데이터베이스 표준(ANSI SQL) 정의상 REPEATABLE READ는 "조회한 데이터의 내용이 바뀌지 않음(Non-Repeatable Read 방지)"만을 보장하며, 새로운 데이터가 끼어드는 Phantom Read는 방지하지 않는다. 하지만 실무에서 가장 많이 쓰이는 DB 엔진들은 더 강력한 메커니즘을 제공한다.
[MySQL (InnoDB)]
MySQL은 REPEATABLE READ가 기본 격리 수준이다. 여기서 MVCC(Multi-Version Concurrency Control)를 이용해 스냅샷을 읽고, Next-Key Lock(Gap Lock)을 통해 데이터 사이의 빈 공간까지 잠금을 걸어 대부분의 Phantom Read를 방지한다.
(완벽한 방지는 아니며, SELECT ... FOR UPDATE 같은 Locking Read나 다른 트랜잭션의 삽입 데이터에 대해 UPDATE를 시도할 경우 Phantom Read가 발생할 수 있다.)
[PostgreSQL]
PostgreSQL은 트랜잭션 진입 시점의 스냅샷을 엄격하게 유지한다. 만약 다른 트랜잭션이 데이터를 변경하여 현재 스냅샷과 충돌이 발생하면(Serialization Failure), 이를 감지하고 해당 트랜잭션을 강제로 롤백(Rollback)시킨다. 즉, 아예 커밋조차 되지 않게 하여 Phantom Read를 원천 차단한다.
| DB | REPEATABLE READ | Phantom Read |
| MySQL(InnoDB) | MVCC + Next-Key Lock | 대부분 방지됨, 일부 Locking Read/Update 상황 예외 |
| PostgreSQL | Snapshot Isolation + Serialization Failure 감지 | 완전 방지 (충돌 시 롤백) |
| 표준 SQL | 구현에 따라 다름 | 보장 하지 않음(발생 가능) |
✅ SERIALIZABLE (Level 3)
SERIALIZABLE은 가장 엄격한 격리 수준으로, 이름 그대로 트랜잭션을 순차적으로 진행시키는 격리수준이다.
SERIALIZABLE에서 여러 트랜잭션이 동일한 레코드에 동시 접근할 수 없으므로, 어떠한 데이터 부정합 문제도 발생하지 않는다. 하지만 트랜잭션이 순차적으로 처리되어야 하므로 동시 처리 성능이 매우 떨어진다.
결국 트랜잭션 격리 수준(Isolation Level) 은 “언제의 데이터를 읽을 것인가”에 대한 선택이다. 트랜잭션이 시작될 때 생성된 스냅샷 시점을 기준으로 데이터 정합성이 유지되며, 이 시점 이후 실제 데이터가 변경되더라도, 트랜잭션 내에서는 여전히 과거의 스냅샷을 바라보게 된다는 것을 이해하고 있으면 좀 더 수월하게 이해 할 수 있을 것 같다.
Reference
https://learn.microsoft.com/en-us/sql/odbc/reference/develop-app/transaction-isolation-levels?view=sql-server-ver16
Transaction Isolation Levels (ODBC) - ODBC API Reference
Transaction Isolation Levels (ODBC)
learn.microsoft.com
https://chaewsscode.tistory.com/201
[DB] 트랜잭션의 격리 수준(Isolation Level)이란?
🌱 트랜잭션 격리 수준(Transaction Isolation Level) 트랜잭션의 격리 수준(Isolation Level)이란 여러 트랜잭션이 동시에 처리될 때, 특정 트랜잭션이 다른 트랜잭션에서 변경하거나 조회하는 데이터를 볼
chaewsscode.tistory.com
https://mangkyu.tistory.com/299
[MySQL] 트랜잭션의 격리 수준(Isolation Level)에 대해 쉽고 완벽하게 이해하기
이번에는 트랜잭션 격리 수준(Isolation Level)에 대해 알아보도록 하겠습니다. 아래의 내용은 RealMySQL과 MySQL 공식 문서 등을 참고하여 작성하였으며, 모든 내용은 InnoDB를 기준으로 설명합니다. 해
mangkyu.tistory.com
