트랜잭션이 데이터 정합성을 보장하려면 여러 개의 트랜잭션이 동시에 실행될 때도 문제가 없어야해요
하지만 무조건 트랜잭션 간의 독립성을 보장하면 성능이 저하될 수도 있어요
이번 글에서는 트랜잭션이 동시에 실행될 때 발생하는 문제, 이를 해결하는 격리 수준(Isolation Levels), 동시성 문제를 해결하는 기법, 교착 상태(Deadlock) 방지 방법도 함께 살펴볼게요.
<트랜잭션 시리즈 개요>
☑️ 1편: 트랜잭션의 개념과 ACID 원칙
✅2편: 트랜잭션의 격리 수준과 동시성 제어 (이번 글)
☑️ 3편: 트랜잭션의 내부 동작과 분산 트랜잭션
☑️ 4편: 트랜잭션의 동작 원리와 직렬성 격리
1. 트랜잭션이 동시 실행될 때 발생하는 문제들
여러 개의 트랜잭션이 동시에 실행되면 데이터 일관성이 깨질 위험이 있어요.
이런 문제를 방지하기 위해 격리 수준을 조절하거나 동시성 제어 기법을 사용해야 해요.
☑️ 더티 읽기 (Dirty Read)
- 트랜잭션이 커밋되지 않은 데이터를 읽는 문제입니다.
- 예를 들어, A 사용자가 상품의 재고를 10개에서 5개로 변경하는 트랜잭션을 실행했어요
- 아직 커밋되지 않았는데 B 사용자가 해당 데이터를 읽으면 재고가 5개로 보일 수 있어요
- 그런데 A 사용자가 트랜잭션을 롤백하면? B 사용자는 존재하지 않는 데이터를 읽은 것이 됩니다.
☑️ 더티 쓰기 (Dirty Write)
- 한 트랜잭션이 다른 트랜잭션이 커밋하지 않은 데이터를 덮어쓰는 문제입니다.
- 예를 들어, A 사용자가 상품 재고를 10개에서 5개로 변경했어요.
- C 사용자가 같은 상품의 재고 데이터를 10개에서 3개로 변경했는데 A의 트랜잭션이 롤백되면 C의 변경 내용도 잘못될 수 있어요.
☑️ 비반복 읽기 (Non-Repeatable Read)
- 같은 데이터를 두 번 읽었을 때 값이 달라지는 문제예요.
- 예를 들어, A 사용자가 상품의 재고를 조회했는데 다른 트랜잭션에서 값이 변경(B 사용자가 재고 변경)되면 다시 조회할 때 값이 달라질 수 있어요.
☑️ 팬텀 읽기 (Phantom Read)
- 특정 조건으로 검색한 데이터가 트랜잭션 실행 중에 변경되는 문제예요.
- 예를 들어, 가격이 20만 원 이하인 상품 목록을 조회했는데
- 다른 트랜잭션이 실행되어 새로운 상품이 추가되거나 기존 상품들의 가격이 변경되면 검색 결과가 달라질 수 있어요
2. 트랜잭션의 격리 수준(Isolation Levels)
이런 동시성 문제를 방지하기 위해 DB의 격리 수준을 조절할 수 있어요.
격리 수준이 높을수록 데이터 정합성이 보장되지만 성능이 낮아지는 단점이 있어요.
→ 격리를 높게하면 트랜잭션 간의 간섭이 줄어들어 정합성이 보장되지만 동시에 처리할 수 있는 트랜잭션의 수는 줄어들어 성능이 낮아집니다.
📌 격리 수준 비교표
격리 수준 더티 읽기 더티 쓰기 비반복 읽기 팬텀 읽기
Read Uncommitted | 허용 | 허용 | 허용 | 허용 |
Read Committed | 방지 | 방지 | 허용 | 허용 |
Repeatable Read | 방지 | 방지 | 방지 | 허용 |
Serializable | 방지 | 방지 | 방지 | 방지 |
다시 한번 이야기 하자면,
격리 수준이 높을수록 데이터 정합성이 보장되지만 트랜잭션 간 충돌(더티 읽기, 더티 쓰기, 비반복 읽기, 팬텀 읽기) 이 증가해서 성능이 저하될 수 있어요.
이제 각 격리 수준에 대해 자세히 살펴볼게요.
1) Read Uncommitted (커밋되지 않은 읽기 허용)
- 가장 낮은 격리 수준이에요.(모든 문제가 발생 가능함)
- 다른 트랜잭션이 커밋하지 않은 데이터를 읽을 수 있어요.
- 성능은 가장 뛰어나겠지만 데이터 정합성이 보장되지 않기 때문에 거의 사용되지 않아요.
☑️ 사용 사례:
- 데이터 정합성이 중요하지 않은 환경 (로그 저장, 캐시 시스템 등)
2) Read Committed (커밋된 데이터만 읽기 허용)
- 커밋된 데이터만 읽을 수 있어요.(더티 읽기/쓰기 문제 해결 ↔ 비반복 읽기, 팬텀 읽기 발생)
- 대부분의 데이터베이스(MySQL, PostgreSQL, Oracle)에서 기본적으로 사용되는 격리 수준이에요.
☑️ 사용 사례:
- 대부분의 일반적인 웹 애플리케이션
3) Repeatable Read (반복 읽기 보장)
- 같은 트랜잭션 내에서 같은 데이터를 여러 번 조회해도 값이 변하지 않아요.(더티 읽기/쓰기 문제, 비반복 읽기 해결 ↔ 팬텀 읽기 발생)
- MySQL InnoDB의 기본 격리 수준이에요.
☑️ 사용 사례:
- 금융 시스템, 쇼핑몰 결제 시스템 등 데이터 정합성이 중요한 서비스
4) Serializable (직렬성 보장, 가장 강력한 격리 수준)
- 모든 트랜잭션이 순차적으로 실행되는 것처럼 동작해요.(더티 읽기/쓰기, 비반복 읽기, 팬텀 읽기 모두 해결)
- 하지만 성능이 크게 저하될 수 있기 때문에 잘 사용되지 않습니다
☑️ 사용 사례:
- 데이터 정합성이 절대적으로 중요한 금융 서비스
3. 동시성 문제 해결 기법
트랜잭션 간의 충돌을 방지하기 위해 잠금(Locking)과 다중 버전 동시성 제어(MVCC) 같은 기법이 사용돼요.
1) 잠금(Locking) 기법
- 공유 잠금(Shared Lock, S-Lock): 여러 트랜잭션이 데이터를 읽을 수 있지만 변경은 불가능해요.
- 배타 잠금(Exclusive Lock, X-Lock): 한 트랜잭션만 데이터를 수정할 수 있어요.
2) 다중 버전 동시성 제어 (MVCC, Multi-Version Concurrency Control)
MVCC는 트랜잭션이 실행될 때 데이터를 읽을 수 있도록 별도의 "스냅샷(Snapshot)"을 유지하는 방식이에요.
즉, 트랜잭션이 실행되는 동안 다른 트랜잭션의 변경 사항을 보지 않고 실행하는 트랜잭션의 시작 시점 데이터를 기준으로 작업을 수행해요
☑️ MVCC의 특징
- 읽기 트랜잭션(Read-Only Transaction)은 잠금 없이 데이터를 조회할 수 있어 성능이 뛰어나요.
- 쓰기 트랜잭션(Write Transaction)은 충돌이 발생하면 롤백될 수도 있어요.
☑️ MVCC 동작 방식
- 트랜잭션이 시작되면 현재 시점의 데이터를 기준으로 "스냅샷"을 생성해요.
- 다른 트랜잭션이 데이터를 변경하더라도 기존 트랜잭션은 자신이 시작할 때 조회한 데이터만 보게 돼요.
- 트랜잭션이 완료되면 최신 데이터로 갱신되거나 충돌이 발생하면 롤백될 수 있어요.
<MVCC를 지원하는 데이터베이스>
MVCC는 MySQL InnoDB, PostgreSQL, Oracle 등의 데이터베이스에서 사용돼요.
예를 들어, PostgreSQL에서는 SELECT 문을 실행할 때 다른 트랜잭션의 변경 사항을 보지 않도록 MVCC를 자동으로 적용해요.
➡ MVCC를 사용하면 트랜잭션 간 충돌을 줄이면서도 읽기 성능을 높일 수 있지만 오래된 데이터 버전을 관리하는 비용이 발생할 수 있어요.
따라서 데이터 변경이 자주 발생하는 시스템에서는 MVCC보다 적절한 잠금 전략을 병행해서 사용하는 것이 중요합니다.!
정리하며
이번 글에서는 트랜잭션의 격리 수준과 동시성 문제 해결 방법을 살펴봤어요.
📌 핵심 정리
☑️ 여러 트랜잭션이 동시에 실행될 때 더티 읽기, 비반복 읽기, 팬텀 읽기 문제가 발생할 수 있어요.
☑️ 격리 수준이 높을수록 데이터 정합성이 보장되지만, 성능이 저하될 수 있어요.
☑️ 잠금(Locking)과 MVCC 같은 기법을 활용하면 동시성 문제를 해결할 수 있어요.
다음 글에서는 트랜잭션의 내부 동작과 분산 트랜잭션에 대해 다룰 예정이에요.
📌 다음 편 예고: "트랜잭션의 내부 동작과 분산 트랜잭션 (3편)"
- 트랜잭션의 내부 동작 (MVCC, Undo Log, Redo Log)
- 2단계 커밋(2PC)과 3단계 커밋(3PC)
- 분산 시스템에서의 트랜잭션 관리 방법
트랜잭션이 실제로 어떻게 동작하는지 자세히 살펴볼게요!
이 글은 마틴 클레프만(Martin Kleppmann)의 데이터 중심 애플리케이션 설계(Designing Data-Intensive Applications) 책을 참고하여 작성되었습니다. 확장 가능하며 유지보수하기 쉬운 데이터 시스템을 설계하는 핵심 개념을 다루고 있습니다.
'Server Developer > DataBase&Data Engineering' 카테고리의 다른 글
트랜잭션이란 무엇인가?(트랜잭션의 기본 개념, 중요성, ACID 원칙) - Part1 (1) | 2025.02.13 |
---|---|
[DataBase] Homebrew를 사용하여 MySQL 설치하기 (Mac M1 Pro) (1) | 2023.01.23 |