[DBS] 트랜잭션 - Part 2. 회복 가능한 스케줄과 비연쇄적 스케줄
지난 글에서는 트랜잭션의 의미와 동작 과정에 대해 살펴보았다. 데이터베이스 시스템에서 트랜잭션의 안정성과 성능을 보장하려면 스케줄의 유형을 이해하는 것이 중요하다. 이번 글에서는 회복 가능한 스케줄과 비연쇄적 스케줄에 대해 알아보자.
회복 가능한 스케줄이란?
회복 가능한 스케줄은 트랜잭션 간의 데이터 읽기와 커밋 순서를 고려하는 스케줄이다.
트랜잭션 Tj가 트랜잭션 Ti가 작성한 데이터를 읽었다면, 반드시 Ti가 먼저 커밋을 해야 Tj도 커밋할 수 있다.
이렇게 해야 하나의 트랜잭션이 실패하더라도 데이터베이스를 일관된 상태로 되돌릴 수 있다.
예를 들어, T1이 데이터 A를 수정하고 T2가 그 데이터를 읽은 다음 커밋하는 경우,
T1이 먼저 커밋한 후에 T2가 커밋해야 회복 가능한 스케줄이 된다.
반대로, T1이 커밋하지 않은 상태에서 T2가 커밋하면, 이후 T1이 실패할 경우 T2도 함께 롤백해야 하므로 데이터 일관성이 깨질 수 있다.
T1: Write(A = 100)
T2: Read(A) ← 100 읽음
T2: Commit
T1: Abort
이 상황에서 T2는 T1의 변경 사항을 읽고 커밋했는데, T1이 나중에 abort됐다.
→ T2는 잘못된 값을 커밋한 셈이 된다.
이런 경우는 복구가 안 된다. 즉 회복 불가능한 스케줄이다.
회복 가능한 스케줄은 데이터베이스의 일관성을 보장하지만, 하나의 트랜잭션이 롤백되면 해당 데이터를 읽은 다른 트랜잭션들도 함께 롤백해야 하는 연쇄적인 롤백(cascading rollback)이 발생할 수 있다는 단점이 있다.
연쇄적 롤백이 발생하는 예를 들어보면,
T1: Write(A)
T2: Read(A) ← T1이 쓴 값을 읽음 (T1 아직 커밋 안 됨)
T3: Read(A) ← T2가 변경한 값 또는 영향을 받은 값
T1: Abort
- 이 스케줄은 우선 회복 가능한 스케줄이다.
왜냐하면 T2, T3는 아직 커밋하지 않았고, T1이 커밋되지 않았기 때문에 커밋을 기다리고 있는 상태이므로,
→ T1이 커밋되면 같이 커밋하고,
→ T1이 abort되면 같이 롤백하면 된다. - 그러나, T1이 abort되면,
→ T2는 T1의 값을 읽었기 때문에 롤백,
→ T3는 T2의 영향을 받았기 때문에 또 롤백...
→ 이렇게 연쇄적 롤백이 발생하게 된다.

비연쇄적 스케줄이란?
비연쇄적 스케줄은 이러한 연쇄적인 롤백을 원천적으로 차단하는 스케줄이다.
이 스케줄에서는 트랜잭션 Tj가 Ti가 작성한 데이터를 읽기 위해서는 Ti가 이미 커밋된 상태여야 한다.
커밋되지 않은 데이터는 절대 읽을 수 없다.
이 방식은 어떤 트랜잭션이 실패하더라도 그 데이터를 읽은 다른 트랜잭션에 영향을 주지 않는다.
따라서 연쇄적인 롤백이 발생하지 않아 시스템의 성능이 향상되고 데이터베이스의 안정성이 높아진다.
Ti: Write(A)
Ti: Commit
Tj: Read(A)
이런 순서여야 비연쇄적이다.
만약 Ti가 커밋되기 전에 Tj가 A를 읽는다면:
Ti: Write(A)
Tj: Read(A)
Ti: Commit
→ 연쇄적 스케줄이 되어 회복이 불가능할 수 있다.
하지만 단점도 존재한다.
모든 트랜잭션이 커밋된 데이터만 읽을 수 있기 때문에 병행성이 다소 떨어진다.
즉, 동시에 처리할 수 있는 작업의 수가 줄어들 수 있다.
결론적으로, 비연쇄적 스케줄은 회복 가능한 스케줄의 조건을 모두 만족하면서 연쇄적인 롤백까지 방지하는 더 엄격한 형태의 스케줄이라고 할 수 있다.
요약 정리
회복 가능한 스케줄 | 비연쇄적 스케줄 | |
데이터 읽기 | 커밋되지 않은 데이터도 읽음 | 커밋된 데이터만 읽음 |
연쇄적 롤백 | 연쇄적 롤백 발생 가능 | 연쇄적 롤백 없음 |
성능 | 롤백 처리 비용 증가할 수 있음 | 롤백 처리 비용 최소화 |
포함 관계 | 비연쇄적 스케줄을 포함하는 더 넒은 개념의 스케줄 | 회복 가능 스케줄 |