직렬 가능 스케줄(Serializable Schedule)은 데이터베이스 트랜잭션의 동시성 제어에서 매우 중요한 개념입니다. 여러 트랜잭션이 동시에 실행될 때, 트랜잭션들의 실행 순서를 제어하여 데이터의 일관성을 보장하는 방법 중 하나입니다. 직렬 가능 스케줄은 직렬 실행(Serial Execution)과 같은 결과를 내는 동시 실행 스케줄을 의미합니다.
직렬 스케줄(Serial Schedule):
트랜잭션들이 순차적으로 하나씩 실행되는 스케줄을 의미합니다. 즉, 한 트랜잭션이 완료된 후에야 다음 트랜잭션이 시작됩니다. 이는 동시성 문제가 발생하지 않지만, 성능이 떨어질 수 있습니다.
예: 트랜잭션 T1이 먼저 끝난 후 트랜잭션 T2가 시작되는 경우입니다.
직렬 가능 스케줄(Serializable Schedule):
여러 트랜잭션이 동시에 실행되지만, 결과적으로 직렬 스케줄과 동일한 결과를 보장하는 스케줄을 말합니다. 즉, 트랜잭션들이 동시에 실행되더라도, 데이터의 일관성을 유지하며, 순차적으로 실행된 것과 같은 결과를 얻습니다.
직렬 스케줄은 직관적이지만 비효율적일 수 있으므로, 직렬 가능 스케줄은 동시성 문제를 해결하면서도 성능을 향상시킬 수 있는 중요한 개념입니다.
트랜잭션이 동시에 실행될 때, 직렬 가능 스케줄이 되려면 동시성 문제를 피하기 위한 조건들이 있습니다. 대표적으로 충돌 직렬 가능성(Conflict Serializable)과 뷰 직렬 가능성(View Serializable)이라는 두 가지 기준이 있습니다.
충돌 직렬 가능성은 트랜잭션 간의 연산 순서에 대한 충돌을 고려하여 직렬 가능성을 판단하는 방법입니다. 트랜잭션 간의 충돌은 동일한 데이터 항목에 대해 동시에 접근할 때 발생하며, 읽기와 쓰기 연산 사이에 충돌이 생길 수 있습니다.
하나의 트랜잭션이 읽기(read)를 수행하고 다른 트랜잭션이 쓰기(write)를 수행하는 경우.
두 트랜잭션이 동시에 쓰기(write)를 수행하는 경우.
이러한 충돌을 피하기 위해, 트랜잭션의 실행 순서를 바꿀 수 있는지 확인하여 충돌 직렬 가능성을 판단합니다.
충돌 직렬 가능성을 판단하는 방법:
예시:
T1: read(A), write(A)
T2: read(A), write(A)
여기서 두 트랜잭션 T1과 T2는 같은 데이터 항목 A를 읽고 쓰기 때문에 충돌이 발생합니다. 이 경우, 두 트랜잭션 간의 충돌 그래프를 그리면, 사이클이 발생하지 않으면 직렬 가능성이 있다고 판단할 수 있습니다.
2.2. 뷰 직렬 가능성(View Serializable)
뷰 직렬 가능성(View Serializable)은 트랜잭션이 데이터를 읽고 쓰는 방식을 기준으로 직렬 가능성을 판단합니다. 뷰 직렬 가능성은 충돌 직렬 가능성보다 덜 엄격한 기준을 사용하지만, 여전히 트랜잭션이 동시에 실행되더라도 직렬 실행과 동일한 결과를 보장할 수 있는지 판단합니다.
뷰 직렬 가능성은 다음을 보장해야 합니다:
직렬 가능 스케줄은 데이터의 일관성 유지와 성능 최적화 사이의 균형을 맞추기 위해 사용됩니다. 동시성 제어를 하지 않고 직렬로만 트랜잭션을 실행하면, 성능이 크게 저하될 수 있습니다. 반면, 모든 트랜잭션을 동시에 실행하면 동시성 문제가 발생할 수 있습니다.
직렬 가능 스케줄을 사용하면:
직렬 가능 스케줄을 구현하기 위해 다양한 동시성 제어 기법이 사용됩니다. 대표적인 기법은 2단계 잠금 규약(2PL, Two-Phase Locking)입니다.
2단계 잠금 규약(2PL)
2PL은 잠금(Lock)을 사용하여 직렬 가능 스케줄을 보장하는 동시성 제어 기법입니다. 트랜잭션이 데이터를 수정하거나 읽을 때, 다른 트랜잭션이 해당 데이터에 접근하지 못하도록 잠금을 겁니다. 2PL은 두 가지 단계로 나뉩니다:
2PL을 사용하면 트랜잭션 간의 충돌을 방지하고, 직렬 가능성을 보장할 수 있습니다. 하지만 교착 상태(Deadlock)가 발생할 수 있다는 단점도 있습니다.
직렬 가능 스케줄은 트랜잭션 동시성 제어에서 데이터의 일관성을 유지하는 핵심 개념입니다. 여러 트랜잭션이 동시에 실행되더라도, 결과적으로 직렬 스케줄과 동일한 결과를 보장하는 것이 직렬 가능 스케줄의 목표입니다. 이를 위해 충돌 직렬 가능성과 뷰 직렬 가능성 같은 기준을 사용하며, 이를 보장하기 위한 다양한 동시성 제어 기법들이 활용됩니다.
충돌 직렬 가능성(Conflict Serializable)과 뷰 직렬 가능성(View Serializable)은 모두 직렬 가능성을 판단하는 기준이지만, 두 개념에는 차이가 있습니다.
정리하자면, 충돌 직렬 가능성은 더 엄격한 충돌 기반의 분석을 통해 직렬 가능성을 판단하는 반면, 뷰 직렬 가능성은 트랜잭션 간 읽기/쓰기 작업의 결과를 기준으로 판단합니다.
네, 2단계 잠금 규약(2PL) 외에도 여러 가지 동시성 제어 기법들이 있습니다. 주요 기법은 다음과 같습니다:
이러한 기법들은 2단계 잠금 규약(2PL)과 달리 잠금 없이 또는 더 적은 잠금을 사용해 동시성 문제를 해결하는 방법입니다.
직렬 가능 스케줄은 트랜잭션의 데이터 일관성을 보장하는 데 유리하지만, 성능에 영향을 줄 수 있습니다. 특히, 직렬 가능성을 보장하기 위해 트랜잭션 간의 충돌을 방지하려면 잠금을 더 오래 유지하거나 충돌 발생 시 롤백을 수행해야 하기 때문에 성능 저하가 발생할 수 있습니다.
성능을 최적화하기 위해 고려해야 할 요소는 다음과 같습니다:
결론적으로, 잠금 범위 관리와 트랜잭션 실행 시간 단축이 직렬 가능 스케줄의 성능 최적화의 핵심이며, 낙관적 동시성 제어나 MVCC 같은 기법을 적절히 사용하면 직렬 가능성을 유지하면서도 성능을 개선할 수 있습니다.