1. 트랜잭션(Transaction)이란?
- 트랜잭션은 하나의 논리적 작업 단위를 말하며, 이 단위 내의 작업이 모두 성공하거나 모두 실패해야 하는 작업 집합.
- 데이터베이스에서는 일관성 있는 상태를 유지하기 위해 반드시 필요한 개념.
- 트랜잭션은 단순히 작업 하나가 아니라, 여러 작업(작업1 → 2 → 3)을 묶은 것.

2. ACID란?
- 데이터베이스 관리 시스템(DBMS)에서 트랜잭션 처리의 신뢰성을 보장하기 위한 네 가지 주요 속성.
- 데이터의 정확성과 일관성을 유지하면서 데이터베이스 시스템이 다양한 오류 상황에서도 신뢰성 있게 동작할 수 있도록 해준다.
2-1. A (Atomicity/원자성)
트랜잭션의 연산은 모두 성공적으로 실행되거나 아무것도 실행되지 않아야 함을 의미한다.
즉, 트랜잭션 내의 모든 작업이 완료되거나, 하나라도 실패할 경우 전체 트랜잭션이 취소되어야 한다.
⚠️ 상황예시 (은행 송금)

A가 B에게 10000원을 송금을 하는 과정을 생각해보자.
이 송금 작업은 다음 두 단계로 이루어진다.
- A계좌에서 10000원을 차감한다.
- B계좌에 10000원을 입금한다.
1번과 2번이 모두 성공해야만 제대로된 송금이 이루어진다.
그런데 1번만 성공하고 2번에서 실패했는데 그대로 저장이 된다면? → A의 돈만 증발한다.
2-2. C (Consistency/일관성)
트랜잭션이 실행되기 전과 후의 데이터베이스 상태는 일관된 규칙을 준수해야 한다.
즉, 트랜잭션이 실행되면 데이터베이스의 모든 데이터는 사전에 정의된 규칙, 제약조건, 트리거 등을 만족해야 한다.
상황예시 (은행 계좌 규칙)

※ 특수한 경우가 아니라면 은행 계좌는 마이너스 금액을 가질 수 없다는 데이터베이스 규칙을 가지고 있다.
A 계좌에 5,000원이 남아 있는 상태에서 A가 B에게 10,000원을 송금하려 한다.
- A계좌에서 10000원을 차감한다.
- A의 계좌가 마이너스가 아니라면? 작업 성공 (다음으로 이동)
- A의 계좌가 마이너스가 된다면? 작업 실패 (ROLLBACK)
- B계좌에 10000원을 입금한다.
1번에서 데이터베이스의 일관성을 위반하기에 모든 작업이 Rollback된다.
2-3. I (Isolation/독립성)
동시에 여러 트랜잭션이 실행될 때, 각 트랜잭션은 다른 트랜잭션의 중간 실행 결과를 볼 수 없다.
이 속성은 각 트랜잭션이 마치 시스템에서 독립적으로 실행되는 것처럼 보장한다.
상황예시 (같은 데이터베이스 공간에서 트랜잭션 A와 트랜잭션 B가 동시에 실행 중)

A의 계좌에 두 개의 트랜잭션이 동시에 발생했다고 가정해보자.
- Transaction A: 5000원 출금 후, 1만 원 입금 (처리 중)
- Transaction B: 현재 잔액 조회
✅ 격리성 보장
Transaction A가 모든 작업을 끝내고 COMMIT(확정)하기 전까지, Transaction B는 A가 수정 중인 중간 값을 읽을 수 없습니다.
→ B는 항상 데이터의 일관성이 보장된 상태만 조회하게 됩니다.
⚠️ 격리 실패
Transaction A가 작업 중인(COMMIT 전) 상태에서 Transaction B가 그 값을 조회할 수 있는 상태입니다.
→ B는 데이터의 보장되지 않은 상태의 값을 조회하게 됩니다.
트랜잭션 격리가 되지 않았을 때 발생하는 몇 가지 문제
- Dirty Read: 다른 트랜잭션이 아직 COMMIT하지 않은 데이터를 읽음
- 계좌 차감(UPDATE) 중인 트랜잭션 A의 '미커밋 데이터(Dirty Data)'를 B가 조회
- B는 최신화되지 않은 계좌를 조회 ❌
- Non-repeatable Read: 동일 트랜잭션 내에서 같은 조건의 SELECT 결과가 달라짐
- 트랜잭션 B가 1차 조회(잔고: 10,000원) → 2차 조회(잔고: 5,000원)
- 트랜잭션 B 내에서 결과 불일치 ❌
- Phantom Read와 비슷한데, Non-repeatable Read은 값 그 자체가 다른 것을 의미
- Phantom Read: 동일 조건의 SELECT에서 행 수가 바뀜 (범위 문제)
- "잔고가 5,000원인 계좌" 조회 (초기 3개) → 재조회 (4개)
- 작업 중 알수 없는 행 추가
- Non-repeatable Read와 비슷한데, Phantom Read은 값의 갯수/범위가 다른 것을 의미
트랜잭션 격리 수준
위에서 언급한 문제를 해결하기 위한 트랜잭션 격리 수준이 있다.
- READ UNCOMMITTED
- Dirty Read 허용 ⚡
- 가장 낮은 수준, 거의 사용하지 않음
- READ COMMITTED
- Dirty Read 방지
- 대부분의 DB 기본값 ⭐
- A가 커밋하기 전까지 B는 보지 못함
- REPEATABLE READ
- Dirty + Non-repeatable Read 방지
- Phantom Read는 허용
- B는 A가 수정 전 조회했던 데이터를 계속 유지함
- SERIALIZABLE
- 모든 문제 방지
- 가장 엄격하지만 성능 저하 큼 ⭐
- A와 B가 아예 동시에 작업 못함 (순차적 실행)
📝 Spring에서의 방지법
@Transactional(isolation = Isolation.REPEATABLE_READ)
public void readMenu() {
// 해당 트랜잭션에서는 Non-repeatable Read 방지
}
- Isolation.DEFAULT = DB 기본값 (MySQL: REPEATABLE_READ, Oracle: READ_COMMITTED)
- Isolation.READ_UNCOMMITTED = Dirty Read 허용, 최고 성능 최저 일관성
- Isolation.READ_COMMITTED = Dirty Read 방지, Non-repeatable Read 발생
- Isolation.REPEATABLE_READ = Dirty/Non-repeatable 방지, Phantom Read 발생
- Isolation.SERIALIZABLE = 모든 이상현상 완전 차단, 순차적 실행처럼 동작
격리 강도: READ_UNCOMMITTED < READ_COMMITTED < REPEATABLE_READ < SERIALIZABLE
2-4. D (Durability/지속성)
트랜잭션이 성공적으로 완료되면, 그 결과는 시스템 오류가 발생하더라도 반드시 영구적으로 데이터베이스에 반영되어야 한다.
즉, 트랜잭션이 커밋되면, 해당 변경 사항은 데이터베이스에 영구적으로 저장될 것이다.
상황예시 (데이터가 보관된 장소에 알수 없는 이슈 발생)

데이터가 저장된 장소에 알수 없는 이유로 인한 정전이 일어났다고 가정해보자.
데이터가 SSD, HDD같은 디스크에 영구적으로 저장되어 있다면 전원만 다시 들어왔을 때 데이터가 그대로 보존되어 있을 것이다.
하지만 Memory같은 휘발성 저장소에 저장되어 있었다면... 전원이 다시 들어와도 데이터가 보존되어 있지 않을 것이다.
- Disk 저장 (튼튼한 금고)
- 데이터가 Disk(SSD/HDD)에 영구 저장.
- 장애가 발생하여 정전/화재에도 복구 → 데이터 손실 없음. ✅
- Memory 저장 (모래성)
- 데이터가 RAM에만 저장.
- 전원 OFF/크래시 시 모든 데이터 증발 🚨
'DB' 카테고리의 다른 글
| [DB] 정규화, 역정규화 (0) | 2026.01.06 |
|---|---|
| [DB] DDL, DML, DCL (0) | 2026.01.05 |