반응형
🔒 트랜잭션 격리 수준(Isolation Level)
📌 격리 수준의 정의
격리 수준은 동시에 실행되는 트랜잭션 간의 데이터 충돌 방지 및 무결성 보장을 위해 설정하는 규칙입니다. 각 수준은 트랜잭션 성능과 일관성 사이에서 트레이드오프를 제공합니다.
격리 수준은 ANSI SQL 표준에 정의되어 있으며, Spring에서는 이를 데이터베이스에 전달하여 적용합니다.
격리 수준 설정 방법
Spring에서 @Transactional
어노테이션에 isolation
속성을 설정하여 격리 수준을 지정할 수 있습니다.
예시 코드
@Transactional(isolation = Isolation.READ_COMMITTED)
public void processData() {
// 트랜잭션 동작
}
📌 격리 수준 값과 특징
아래는 Spring과 ANSI SQL에서 제공하는 주요 격리 수준과 각 문제를 방지하는 방법입니다.
격리 수준 | 설명 | 방지되는 문제 | 발생 가능한 문제 |
READ_UNCOMMITTED |
커밋되지 않은 데이터 읽기 가능 | 없음 | Dirty Read 발생 |
READ_COMMITTED |
커밋된 데이터만 읽기 가능 | Dirty Read 방지 | Non-Repeatable Read 발생 |
REPEATABLE_READ |
동일 데이터 트랜잭션 동안 일관성 유지 | Dirty Read, Non-Repeatable Read 방지 | Phantom Read 발생 |
SERIALIZABL E |
트랜잭션 순차 실행으로 완전 격리 | Dirty Read, Non-Repeatable Read, Phantom Read 방지 | 성능 저하, 교착 상태 발생 가능 |
📌 주요 문제와 격리 수준 적용 사례
1️⃣ Dirty Read (더티 읽기)
Dirty Read는 커밋되지 않은 데이터를 읽는 문제로, 롤백된 데이터가 다른 트랜잭션에 영향을 줄 수 있습니다.
문제 상황
- 트랜잭션 A가 데이터를 수정했으나 커밋하지 않음.
- 트랜잭션 B가 수정 중인 데이터를 읽음.
- 트랜잭션 A가 롤백되면, 트랜잭션 B는 잘못된 데이터를 사용하게 됨.
해결 방법
- 격리 수준을
READ_COMMITTED
이상으로 설정.
2️⃣ Non-Repeatable Read (불일치 읽기)
Non-Repeatable Read는 같은 데이터를 반복 조회할 때 값이 달라지는 문제입니다.
문제 상황
- 트랜잭션 A가 데이터를 읽음.
- 트랜잭션 B가 데이터를 수정하고 커밋.
- 트랜잭션 A가 같은 데이터를 다시 읽으면 값이 달라짐.
해결 방법
- 격리 수준을
REPEATABLE_READ
이상으로 설정.
3️⃣ Phantom Read (팬텀 읽기)
Phantom Read는 조건에 맞는 데이터 집합이 트랜잭션 도중에 변경되는 문제입니다.
문제 상황
- 트랜잭션 A가
WHERE
조건으로 데이터를 조회. - 트랜잭션 B가 새로운 데이터를 추가하거나 삭제하고 커밋.
- 트랜잭션 A가 같은 조건으로 다시 조회하면 결과 집합이 달라짐.
해결 방법
- 격리 수준을
SERIALIZABLE
로 설정.
📌 격리 수준 예제
1️⃣ READ_UNCOMMITTED
예제 (Dirty Read 허용)
@Transactional(isolation = Isolation.READ_UNCOMMITTED)
public void processUncommittedData() {
// 커밋되지 않은 데이터 읽기 가능
}
- 사용 사례: 성능이 가장 중요한 경우. 데이터 정확성보다 속도가 더 중요할 때 사용.
- 문제: Dirty Read 발생.
2️⃣ READ_COMMITTED
예제 (Dirty Read 방지)
@Transactional(isolation = Isolation.READ_COMMITTED)
public void processCommittedData() {
// 커밋된 데이터만 읽기
}
- 사용 사례: 대부분의 애플리케이션에서 사용. 데이터 정확성을 어느 정도 보장하면서 성능 손실이 적음.
- 문제: Non-Repeatable Read 발생.
3️⃣ REPEATABLE_READ
예제 (Non-Repeatable Read 방지)
@Transactional(isolation = Isolation.REPEATABLE_READ)
public void processRepeatableData() {
// 트랜잭션 동안 동일 데이터 일관성 유지
}
- 사용 사례: 데이터 정확성이 중요한 시스템(은행, 회계 시스템 등).
- 문제: Phantom Read 발생 가능.
4️⃣ SERIALIZABLE
예제 (팬텀 읽기 방지)
@Transactional(isolation = Isolation.SERIALIZABLE)
public void processSerializableData() {
// 트랜잭션 순차 실행
}
- 사용 사례: 데이터 일관성이 가장 중요할 때(예: 금융 거래).
- 문제: 높은 동시성 요구 시스템에서는 성능 저하 발생 가능.
📌 스냅샷과 MVCC (Multi-Version Concurrency Control)
스냅샷이란?
스냅샷은 트랜잭션이 시작된 시점의 데이터 상태를 캡처하여, 트랜잭션 동안 일관성을 유지합니다.
MVCC 동작 방식
- 스냅샷 데이터는 데이터베이스 엔진의 Undo Log 또는 메모리에 저장.
- 각 트랜잭션은 스냅샷을 기반으로 읽기 작업을 수행하므로 다른 트랜잭션의 변경에 영향을 받지 않음.
스냅샷 저장 위치
- 데이터베이스 서버의 메모리 또는 Undo Log에 저장.
- WAS(Application Server)로 올라가지 않음.
📌 격리 수준 선택 기준
- 성능이 중요한 경우:
READ_UNCOMMITTED
또는READ_COMMITTED
. - 데이터 정확성이 중요한 경우:
REPEATABLE_READ
. - 가장 높은 일관성이 필요한 경우:
SERIALIZABLE
.
🚀 요약
- 트랜잭션 격리 수준
READ_UNCOMMITTED
: Dirty Read 허용. 성능 우선.READ_COMMITTED
: Dirty Read 방지. 일반적인 설정.REPEATABLE_READ
: Non-Repeatable Read 방지.SERIALIZABLE
: 가장 높은 일관성 제공. 성능 저하 가능.
- 스냅샷과 MVCC
- 스냅샷 기반으로 읽기 일관성을 유지.
- Undo Log 또는 메모리에서 관리.
- 주요 문제와 해결 방법
- Dirty Read:
READ_COMMITTED
이상. - Non-Repeatable Read:
REPEATABLE_READ
이상. - Phantom Read:
SERIALIZABLE
.
- Dirty Read:
반응형
'Java' 카테고리의 다른 글
[JAVA] ArrayList vs LinkedList 완벽 정리 (0) | 2024.12.31 |
---|---|
[JAVA] Queue와 Deque 무엇이 좋을까? (2) | 2024.12.27 |
[JAVA] @Transactional 알아보기 Part.2 #전파(Propagation) (0) | 2024.12.24 |
[JAVA] @Transactional 알아보기 Part.1 #프록시와 트랜잭션 동작 원리 (0) | 2024.12.23 |
[JAVA] Spring 공통 모듈을 패키지화하고 GitHub Packages에 등록하는 방법 (0) | 2024.12.06 |