트랜잭션 스케줄은 왜 회복 가능해야 할까?
Recoverable / Cascadeless / Strict Schedule 완전 정리
데이터베이스는 동시성(Concurrency)을 보장해야 하지만, 동시에 발생하는 트랜잭션이 모두 문제없이 끝나는 것은 아닙니다. 일부 트랜잭션은 롤백되기도 하고, 이로 인해 다른 트랜잭션까지 영향을 받을 수 있습니다.
따라서 DBMS는 단순히 serializable한 스케줄만을 고려해서는 안 되며, rollback 상황에서도 데이터 정합성을 유지할 수 있는 스케줄, 즉 **회복 가능한 스케줄(Recoverable Schedule)**을 반드시 보장해야 합니다.
1. 스케줄(Schedule) 복습
스케줄이란, 여러 트랜잭션의 연산(read/write)이 실제로 어떤 순서로 실행되었는지를 표현한 것입니다.
다양한 동시성 제어를 통해 트랜잭션은 얽혀 실행되는데, 이때 스케줄의 안전성은 다음과 같은 개념으로 구분됩니다:
2. 회복 가능한 스케줄 (Recoverable Schedule)
정의
스케줄 내에서 어떤 트랜잭션도, 자신이 읽은 데이터를 작성한 트랜잭션이 commit되기 전에는 commit하지 않는 스케줄.
예시 상황
T1: W1(A) → (아직 commit 안 함)
T2: R2(A) → C2 ← 문제 발생 가능성 있음
- T2는 T1이 쓴 값을 읽고 commit했는데,
- 이후 T1이 실패하고 rollback된다면?
- → T2는 잘못된 값을 보고 commit한 것이 됨
결론
→ T2는 T1이 먼저 commit한 이후에만 commit해야 함
→ 그래야 T1이 rollback되면 T2도 commit하지 않게 막을 수 있음
3. 회복 불가능한 스케줄 (Unrecoverable Schedule)
정의
다른 트랜잭션이 작성한 값을 읽고 commit했는데, 그 작성자가 나중에 rollback되는 경우.
문제점
- 이미 커밋된 트랜잭션이 잘못된 데이터를 반영한 상태
- 이 시점에서 rollback이 불가능
- → 데이터 정합성 손상
DBMS는 이러한 스케줄을 절대 허용하지 않아야 합니다.
4. Cascading Rollback (연쇄 롤백)
이제 회복 가능은 하지만, 문제가 생길 수 있는 경우를 살펴보겠습니다.
T1: W1(A) → (아직 commit 안 함)
T2: R2(A) → ...
T3: R3(A) → ...
- T2와 T3는 T1의 데이터를 읽었지만 아직 commit하지 않음
- 이 상태에서 T1이 rollback되면?
- → T2, T3도 모두 rollback해야 함
문제점
- 의존된 모든 트랜잭션을 연쇄적으로 rollback
- → 처리 비용 큼, 오류 추적 복잡, 사용자 응답 지연
5. Cascadeless Schedule
정의
Commit되지 않은 트랜잭션이 write한 데이터를 읽지 않는 스케줄
효과
- 읽는 입장에서 항상 확정된(Commit된) 데이터를 보기 때문에,
- rollback 시 연쇄적으로 다른 트랜잭션을 건드릴 일이 없음
T1: W1(A) → C1
T2: R2(A after C1) → C2
→ 연쇄 rollback 없음 → 안정적
→ 대부분의 DBMS는 cascadeless 스케줄만 허용하도록 제어함
6. Strict Schedule
정의
어떤 트랜잭션도 commit되지 않은 트랜잭션이 write한 데이터를 읽지도 쓰지도 않는 스케줄
Cascadeless + 추가 제약
장점
- 시스템이 트랜잭션을 rollback할 때 되돌릴 대상이 명확함
- undo log 또는 redo log에서 복구가 단순
- 거의 모든 DBMS가 실무에서는 이 스케줄을 구현함
7. 관계 정리
concurrency control의 목표는?
serializability (정상적인 결과)
recoverability (문제 생겨도 복구 가능)
8. 계층 구조 요약
| 스케줄 유형 | 설명 | 포함 관계 |
| Strict Schedule | commit 전 write값을 읽거나 쓰는 것조차 금지 | ⊂ Cascadeless |
| Cascadeless | commit 전 write값을 읽는 것 금지 | ⊂ Recoverable |
| Recoverable | write한 트랜잭션이 commit한 뒤에만 commit | ⊂ All serializable |
| Unrecoverable | rollback된 값 읽고 commit하는 경우 → 복구 불가 | ❌ DBMS에서 금지해야 함 |

+추가사항(개인적으로 헷갈렸던 것!!)
Cascadeless 에서 write는 왜 허용해줬을까?
read는 데이터를 변경시키지 않고 write는 변경시키는데 더 위험한 write를 금지해야하는게 아닌가? 라고 생각했다.
* 이걸 이해하려면 **“rollback 시 영향을 받는 대상이 누구인가?”**를 생각해야 합니다.
핵심 요지 먼저
Read는 의존을 만들고,
Write는 덮어쓰는 것뿐이므로 rollback 의존성을 만들지 않는다.
1. Cascading Rollback이 왜 생기나?
시나리오
T1: W1(A)
T2: R2(A) → C2
- T1이 A를 썼고, 아직 commit하지 않았는데
- T2가 그 값을 읽고 commit
이때 T1이 rollback되면?
→ T2는 이미 잘못된 값을 보고 commit한 상태
→ T2도 rollback해야 함 (cascading rollback)
2. 그런데 write는 왜 괜찮을까?
시나리오
T1: W1(A)
T2: W2(A)
- T1이 A를 썼고, 아직 commit하지 않았는데
- T2도 A를 바로 덮어씀 (T1의 값은 사용하지 않음)
이때 T1이 rollback되더라도
→ T2는 T1의 값을 읽거나 사용하지 않았음
→ T2는 롤백할 필요가 없음
즉, T2는 T1에 의존하지 않는다.
9. 마무리
트랜잭션은 성능과 일관성 사이에서 균형을 찾아야 합니다.
Serializability는 정확한 결과를 위한 기준이고,
Recoverability는 장애 상황에서도 시스템의 신뢰성을 보장하는 조건입니다.
Strict Schedule은 보수적이지만, 데이터 정합성과 복구의 용이성을 위해 현실에서 가장 많이 사용되는 전략입니다.
DBMS의 concurrency control은 단순히 충돌을 피하는 것 이상으로, 복구가 가능한 안전한 상태까지 고려해야 합니다.
'CS지식 > 데이터베이스 (Database)' 카테고리의 다른 글
| (데이터베이스) Lock, Two-Phase Locking(2PL), 데드락 정리(예제 포함) (0) | 2025.05.21 |
|---|---|
| (DB)트랜잭션 이상 현상 , Isolation Level 정리 (SQL-92 기준) (0) | 2025.05.20 |
| (데이터베이스) 트랜잭션 스케줄링과 Serializability 정리 (0) | 2025.05.19 |
| (데이터베이스) 트랜잭션과 ACID 완전 정리 (Oracle 중심 + Java 예제 포함) (0) | 2025.05.19 |
| (데이터베이스)트리거(Trigger)란? — Oracle 기준으로 정리하는 SQL 트리거의 개념과 실무 주의사항 (0) | 2025.05.17 |