eelseungmin

Concurrency Control (3) - Lock을 활용한 기법

by eelseungmin

들어가며

이번엔 Lock을 활용해 Concurrency Control을 하는 방법에 대해 설명하고자 한다.

3편에 앞서 먼저 1편과 2편을 읽어보는 것을 권한다.

 

Lock을 사용하는 이유

write 연산과 read 연산을 할 때 여러 트랜잭션이 같은 데이터에 접근하다 보면 이로 인해 예상치 못한 이상현상이 나타날 수 있다. 그래서 lock을 통해 사용하는 데이터를 잠가두는 방식을 활용하는 것이다.

다음은 간단한 예시이다.

tx1에서 x에 대한 write lock을 획득하고, tx2에서 lock 획득을 시도하지만 이미 tx1에서 lock을 가지고 있기 때문에 lock을 얻기 위해 대기하게 된다. 그러고 나서 tx1이 x를 20으로 바꾼 뒤 lock을 반환한다. 그러면 드디어 tx2에서 write lock을 얻은 뒤 x를 90으로 변경하는 것이다.

 

이제 write lock과 read lock에 대해서 알아보자.

 

Write Lock(Exclusive Lock)

read 혹은 write 연산에서 사용하며, 다른 tx가 같은 데이터를 read하거나 write하는 것을 허용치 않는다.

 

Read Lock(Shared Lock)

read 연산에서 사용하며, 다른 tx가 같은 데이터를 read하는 것은 허용한다. 물론 여전히 write하는 것은 허용치 않는다.

 

두 Lock 간의 호환성

  Read Lock Write Lock
Read Lock O X
Write Lock X X

 

Lock을 사용했음에도 이상현상이 발생한다?

다음 예시를 살펴보자.

위 그림에서 구분선 왼쪽의 연산만 모은 것을 t1, 오른쪽의 연산만 모은 것을 t2라고 했을 때 t1->t2, t2->t1의 순서로 각각 실행했을 때의 결과를 생각하면서 예제를 보자.

 

그림에 나온 일련의 연산을 수행했을 때 결과는 x=300, y=300이 나오게 되는데 이는 빨갛게 표시해둔 serial schedule의 결과와 일치하지 않으므로 위 스케줄은 nonserializable하다고 볼 수 있다.

결과적으로 lock을 사용한다고 해서 스케줄이 serializable한 것은 아니라는 점을 알 수 있다.

 

이상현상 해결하기(feat. 2PL protocol, two-phase locking protocol)

그렇다면 어떻게 문제를 해결할 수 있을까?

주황색으로 표시한 부분의 순서를 바꾸면, y에 대한 write lock을 tx2가 가지고 있기 때문에 tx1의 연산들이 전부 뒤로 미뤄지게 되고 그 사이에 tx2의 작업들이 수행될 것이다.

 

위 설명을 그림으로 다시 표현하면 다음 그림이 될 것이다.

위 스케줄의 결과는 serial schedule 2의 결과처럼 x=400, y=300이 된다.

 

여기서 lock에 관련된 연산만 떼어보자.

tx1과 tx2의 연산 각각 unlock에 앞서 lock을 획득하는 연산이 끝난 모습이다.

이처럼 tx에서 모든 locking 연산이 최초의 unlock 연산보다 먼저 수행되도록 하는 것을 2PL protocol이라고 한다.

lock을 획득하기만 하고 반환하지 않는 phase를 expanding phase,

lock을 반환하기만 하고 획득하지 않는 phase를 shirinking phase라고 표현한다.

또한 2PL protocol에서는 serializability를 보장한다.

 

그리고 2PL protocol에서 deadlock이 발생하는 경우가 있는데, 이를 해결하는 방법은 OS에서 deadlock을 해결하는 방법과 비슷하다.

 

Conservative 2PL

모든 lock을 획득한 뒤 tx를 시작하는 방식이다. 즉 lock을 획득한 뒤부터 read 또는 write 연산이 수행된다.

deadlock이 발생하지 않는다는 장점이 있으나, 모든 lock을 획득하기 어려운 상황이 있을 수 있어서 실용성이 떨어진다.

 

Strict 2PL(S2PL)

strict schedule을 보장하는 방식이다. write lock을 획득한 tx가 commit되거나 rollback될 때 lock을 반환한다.

 

Strong Strict 2PL(SS2PL)

strict schedule을 보장하는 또 다른 방식이다. 여기서는 write lock 뿐만 아니라 read lock 또한 획득한 tx가 commit되거나 rollback될 때 lock을 반환한다.

S2PL에 비해 구현이 쉽지만 상대적으로 lock을 오랫동안 들고 있기 때문에 성능이 떨어질 수 있다.

 

가장 많이 사용되는 방식은 S2PL과 SS2PL이다.

 

Lock을 사용한 Concurrency Control 기법의 단점

아까 Lock 간 호환성을 표현한 표에서 봤듯이 lock을 사용한 기법에는 read lock과 read lock이 맞물리는 상황이 아니라면 lock 반환까지 대기해야 하므로 그만큼 처리량이 떨어진다는 단점이 있다.

 

여러 상용 RDBMS에서는 read와 write 간에 서로를 block하는 것을 해결해서 처리량을 끌어올리기 위해 MVCC라는 방식을 도입했고, 다음 편에서는 이에 대해 알아보겠다.

블로그의 정보

eel.log

eelseungmin

활동하기