Two-Phase Locking(2PL)은 트랜잭션이 데이터를 읽고 쓰기 위해 잠금(lock)을 설정할 때 두 가지 단계로 나뉩니다. 이 방식은 트랜잭션이 잠금을 설정하는 "확장 단계"와 잠금을 해제하는 "축소 단계"로 구분됩니다. 중요한 점은 트랜잭션이 잠금을 해제하기 전까지는 자유롭게 잠금을 설정할 수 있지만, 잠금을 한 번 해제하기 시작하면 더 이상 잠금을 설정할 수 없다는 규칙입니다.
2PL의 단계:
1. 확장 단계(Growing Phase): 트랜잭션이 필요한 데이터에 대해 잠금을 설정할 수 있습니다. 이 단계에서는 새로운 잠금을 자유롭게 설정할 수 있습니다.
이 규칙에 의해, 2PL은 충돌 직렬 가능성(Conflict Serializable)을 보장하여 여러 트랜잭션이 동시에 실행될 때 데이터 무결성을 유지할 수 있습니다.
2PL 예시:
다음은 트랜잭션 T1과 T2가 2PL 규약을 따르는 예시입니다.
여기서 2PL은 T1이 먼저 잠금을 설정하고 해제할 때까지, T2가 A에 접근할 수 없게 함으로써 충돌을 방지합니다.
Strict Two-Phase Locking(Strict 2PL)은 2PL의 특수한 경우로, 더 엄격한 규칙을 따릅니다. Strict 2PL에서는 쓰기 잠금(Exclusive Lock)을 트랜잭션이 완료될 때까지(Commit 또는 Rollback) 해제하지 않습니다. 즉, 쓰기 작업이 끝났다고 해서 잠금을 바로 해제하지 않고, 트랜잭션이 완전히 커밋되기 전까지 잠금을 유지합니다.
이 방식은 Dirty Read(커밋되지 않은 데이터를 읽는 문제)와 Lost Update(갱신 손실)를 방지하는 데 효과적입니다.
Strict 2PL의 단계:
1. 확장 단계(Growing Phase): 트랜잭션이 잠금을 설정하는 단계입니다. 트랜잭션은 읽기 잠금(Shared Lock)과 쓰기 잠금(Exclusive Lock)을 설정할 수 있습니다.
Strict 2PL에서는 쓰기 작업을 완료했더라도, 트랜잭션이 끝나기 전까지는 다른 트랜잭션이 해당 데이터를 읽을 수 없게 만듭니다.
Strict 2PL 예시:
같은 예시에서 Strict 2PL을 적용해보겠습니다.
1.T1: 계좌 A에 배타 잠금(Exclusive Lock)을 설정하고, A에서 100을 출금
2. T2: 계좌 A의 잔액을 조회하려 하지만, Strict 2PL 규칙에 의해 A의 쓰기 잠금이 트랜잭션이 커밋될 때까지 유지되므로, T2는 대기 상태
3. T1: 계좌 B에 배타 잠금을 설정하고, B에 100을 입금
4. T1: 트랜잭션 완료 후, 커밋 시점에 계좌 A와 B의 잠금을 해제
5. T2: 이제 계좌 A에 접근하여 잔액을 조회 가능
여기서 Strict 2PL은 T1이 계좌 A와 B에 대해 쓰기 작업을 마친 후에도 커밋되기 전까지 잠금을 유지하여, T2가 커밋되지 않은 데이터를 읽는 것을 방지합니다. 이는 Dirty Read를 방지하는 역할을 합니다.
| 구분 | 2단계 잠금 규약(2PL) | Strict 2단계 잠금 규약(Strict 2PL) |
|---|---|---|
| 잠금 해제 시점 | 읽기 및 쓰기 잠금을 트랜잭션의 실행 중에 해제할 수 있음 | 쓰기 잠금은 트랜잭션이 커밋 또는 롤백될 때까지 유지 |
| Dirty Read 방지 | 방지하지 않음. 다른 트랜잭션이 커밋되지 않은 데이터를 읽을 수 있음 | Dirty Read를 방지. 트랜잭션이 완료되기 전까지 쓰기 작업이 완료된 데이터는 다른 트랜잭션이 읽을 수 없음 |
| 갱신 손실(Lost Update) | 트랜잭션이 작업 중에 잠금을 해제할 수 있어 갱신 손실이 발생할 가능성이 있음 | 갱신 손실 방지. 트랜잭션이 완료되기 전까지 다른 트랜잭션이 동일 데이터를 수정할 수 없도록 배타 잠금을 유지 |
| 복잡도 | 단순. 기본적인 충돌 직렬 가능성을 보장하는 잠금 기법 | 조금 더 엄격한 규칙을 적용하여, 동시성 제어에 있어 더 강력한 무결성 보장 |
Strict 2PL은 데이터 무결성을 더욱 강력하게 보장하기 위해 사용됩니다. 다음과 같은 이유 때문에 Strict 2PL이 필요할 수 있습니다:
하지만 Strict 2PL은 동시성 성능에 더 많은 제약을 가합니다. 트랜잭션이 완료될 때까지 쓰기 잠금을 해제하지 않기 때문에 다른 트랜잭션들이 더 오래 대기해야 할 수 있습니다. 따라서 동시성 성능과 데이터 무결성 사이의 트레이드오프를 고려하여 사용하는 것이 좋습니다.
2PL과 Strict 2PL의 성능 차이는 트랜잭션의 쓰기 작업이 얼마나 자주 발생하고, 트랜잭션의 길이에 따라 크게 달라집니다.
결론적으로, Strict 2PL은 트랜잭션이 짧거나 쓰기 작업이 적을 때 성능 저하가 크지 않지만, 긴 트랜잭션이나 쓰기가 자주 발생하는 환경에서는 성능 차이가 크게 나타날 수 있습니다.
Strict 2PL은 교착 상태(Deadlock)가 발생할 가능성을 높입니다. 이는 트랜잭션이 완료될 때까지 쓰기 잠금을 오래 유지하기 때문입니다. 교착 상태는 두 트랜잭션이 서로 잠금을 기다리면서 무한 대기 상태에 빠지는 상황을 말합니다. 이를 해결하는 방법은 여러 가지가 있습니다:
Strict 2PL에서는 이러한 방법들을 적용하여 교착 상태를 해결하거나 예방할 수 있으며, 특히 타임아웃과 탐지 알고리즘이 많이 사용됩니다.
Strict 2PL은 갱신 손실(Lost Update)과 더티 리드(Dirty Read)를 방지하는 것 외에도 다음과 같은 중요한 장점들을 제공합니다:
결론적으로, Strict 2PL은 다른 동시성 제어 기법에 비해 더 강력한 일관성 보장을 제공하며, 데이터 무결성을 유지해야 하는 환경에서 매우 유용한 기법입니다. 다만, 이로 인해 동시성 성능이 저하될 수 있다는 단점도 고려해야 합니다.