둘 이상의 트랜잭션이 서로가 잠금을 포기하기를 기다리는 상황(교착상태)을 말합니다.
데드락 예시
Transaction A: Lock(X) → Wait for Lock(Y)
Transaction B: Lock(Y) → Wait for Lock(X)
A는 Y를 기다리고, B는 X를 기다리며
서로 영원히 대기하는 교착상태 발생
데드락 발생 조건
다음 4가지 조건이 동시에 충족될 때 데드락 발생
1. 상호 배제 (Mutual Exclusion)
자원은 한 번에 하나의 트랜잭션만 사용할 수 있습니다.
-- 트랜잭션 A가 Row 1을 잠금
-- 트랜잭션 B는 Row 1에 동시 접근 불가
2. 점유 및 대기 (Hold and Wait)
트랜잭션이 최소한 하나의 자원을 점유하고 있으면서 다른 트랜잭션이 점유한 자원을 추가로 요구할 때 발생합니다.
T1: 자원 A 보유 → 자원 B 요청
T2: 자원 B 보유 → 자원 A 요청
3. 비선점 (No Preemption)
한 트랜잭션이 점유한 자원은 그 트랜잭션이 명시적으로 해제할 때까지 다른 트랜잭션에 의해 강제로 빼앗길 수 없습니다.
T1이 자원을 보유 중
→ T2가 강제로 빼앗을 수 없음
→ T1이 자발적으로 해제할 때까지 대기
4. 순환 대기 (Circular Wait)
각 트랜잭션이 순환적으로 다음 트랜잭션에 의해 점유된 자원을 대기하는 상태입니다.
T1 → (T2가 보유한 자원 대기) → T2
T2 → (T3가 보유한 자원 대기) → T3
T3 → (T1이 보유한 자원 대기) → T1
순환 고리 형성
데드락 해결 방법
1. Timeout (시간 초과)
일정 시간 이후 트랜잭션이 실행되지 않았을 경우 롤백합니다. 직접적으로 탐지하는 것은 아니지만 일정 시간 이후 트랜잭션이 실행되지 않음을 교착상태로 정의해서 탐지하는 방법입니다.
장점
- 구현이 간단
- 데드락 상황을 빠르게 해결 가능
단점
- 시간 설정이 어려움
- 실제 데드락이 아닌 상황에서도 트랜잭션이 중단될 수 있음
-- MySQL 예시
SET innodb_lock_wait_timeout = 50; -- 50초 대기 후 롤백
2. Wait-for Graph (대기 그래프)
트랜잭션에 관한 대기 그래프를 만들고 해당 그래프에 사이클이 발생됨을 주기적으로 검사합니다.
Wait-for Graph 예시:
T1 → T2 → T3 → T1 (사이클 발견 → 데드락!)
단점:
대규모 데이터베이스의 경우 모든 트랜잭션의 사이클을
찾아 데드락을 감지하는 것은 코스트가 커서 잘 사용하지 않음
데드락 방지 (Prevention)
1. 격리 수준 변경
데드락을 방지하기 위해 격리 수준을 조정하는 것을 말합니다.
-- 낮은 격리 수준 사용
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
-- 데드락 위험 감소, 대신 일관성 문제 발생 가능
2. 자원 할당 순서 지정
서비스 로직을 구축할 때 자원 할당이 교착상태가 발생하지 않도록 서비스의 논리 구조를 바꾸는 것을 말합니다.
데드락 발생 가능:
T1: Lock(계좌A) → Lock(계좌B)
T2: Lock(계좌B) → Lock(계좌A)
순서 지정으로 방지:
T1: Lock(계좌A) → Lock(계좌B)
T2: Lock(계좌A) → Lock(계좌B)
(항상 A → B 순서로 잠금)
3. Wait-Die 방법 (비선점 기법)
타임스탬프를 기반으로 오래된 트랜잭션을 더 우선순위가 높다고 판정하여 이에 따라 대기, 강제 종료 등을 하는 방식을 가진 비선점 기법입니다.
Wait (대기)
우선순위가 높은 트랜잭션이 자원을 요청했을 때, 그 자원이 이미 우선순위가 낮은 트랜잭션에 의해 점유되어 있으면, 우선순위가 높은 트랜잭션은 대기 상태로 들어갑니다.
Die (종료)
우선순위가 낮은 트랜잭션이 자원을 요청했을 때, 그 자원이 이미 우선순위가 높은 트랜잭션에 의해 점유되어 있으면, 우선순위가 낮은 트랜잭션은 롤백되고, 나중에 다시 시도합니다.
예시 (타임스탬프가 작을수록 오래됨 = 우선순위 높음):
T1 (timestamp: 100) - 우선순위 높음
T2 (timestamp: 200) - 우선순위 낮음
상황 1: T1이 T2가 보유한 자원 요청
→ Wait: T1 대기 (우선순위 높은 트랜잭션이므로)
상황 2: T2가 T1이 보유한 자원 요청
→ Die: T2 롤백 (우선순위 낮은 트랜잭션이므로)
4. Wound-Wait 방법 (선점 기법)
타임스탬프를 기반으로 오래된 트랜잭션을 더 우선순위가 높다고 판정하여 이에 따라 대기, 강제 종료 등을 하는 방식을 가진 선점 기법입니다.
Wound (부상)
우선순위가 높은 트랜잭션이 자원을 요청했을 때, 그 자원이 이미 우선순위가 낮은 트랜잭션에 의해 점유되어 있으면, 우선순위가 낮은 트랜잭션을 부상시킵니다. 해당 트랜잭션의 점유 자원을 강제 해제하고 우선순위가 높은 트랜잭션에게 넘겨줍니다.
Wait (대기)
우선순위가 낮은 트랜잭션이 자원을 요청했을 때, 그 자원이 이미 우선순위가 높은 트랜잭션에 의해 점유되어 있으면, 우선순위가 낮은 트랜잭션은 높은 우선순위를 가진 트랜잭션이 해제될 때까지 기다립니다.
예시:
T1 (timestamp: 100) - 우선순위 높음
T2 (timestamp: 200) - 우선순위 낮음
상황 1: T1이 T2가 보유한 자원 요청
→ Wound: T2 강제 종료, T1에게 자원 넘김 (선점)
상황 2: T2가 T1이 보유한 자원 요청
→ Wait: T2 대기
Wait-Die vs Wound-Wait 비교
| 특성 | Wait-Die (비선점) | Wound-Wait (선점) |
| 우선순위 높음 → 낮음 | Wait (대기) | Wound (강제 종료) |
| 우선순위 낮음 → 높음 | Die (롤백) | Wait (대기) |
| 자원 강제 회수 | 불가능 | 가능 |
| 롤백 빈도 | 높음 | 낮음 |
'ZeroBase > CS' 카테고리의 다른 글
| MySQL 스토리지 엔진(InnoDB vs MyISAM) (0) | 2025.10.16 |
|---|---|
| 데이터베이스 정규화 - 이상 현상 해결과 정규형 (0) | 2025.10.12 |
| Clustered Index vs Non-Clustered Index (0) | 2025.09.30 |
| 데이터베이스 인덱스 - B-Tree와 성능 최적화 (0) | 2025.09.30 |
| 트랜잭션 격리 수준과 발생 가능한 현상 (0) | 2025.09.30 |