본문 바로가기
DataBase/MySQL

[MySQL] Lock을 활용한 concurrency control (2PL)

by 제우제우 2024. 11. 14.

참고 자료 

유투브 쉬운코드 LOCK을 활용한 concurrency control

Lock

데이터베이스 락(lock)은 동시성 문제를 방지하고 데이터의 무결성을 유지하기 위해 필수적이다.
락을 걸지 않으면 여러 트랜잭션이 동시에 동일한 데이터를 수정하려고 할 때 충돌이 발생하여 데이터가 손상되거나 일관성을 잃을 수 있다. 

즉, 이상 현상이 일어날 수 있다. 

예제1

 

흐름 

x 시작: 50 

트랜잭션1: write_lock 획득 

트랜잭션2: write_lock 획득 X

트랜잭션1: x = 20 변경

트랜잭션1: write_lock 반환

트랜잭션2: write_lock 획득

트랜잭션2: x = 90 변경

트랜잭션2: write_lock 반환

예제2

 

흐름 

x 시작: 10

트랜잭션1: write_lock 획득

트랜잭션2: read_lock 획득 X

트랜잭션1: x = 20 변경

트랜잭션1: write_lock 반환

트랜잭션2: read_lock 획득 

트랜잭션2: x read(20)

트랜잭션2: read_lock 반환

write_lock (exclusive lock)

read/write(insert, update, delete) 할 때 사용한다

다른 트랜잭션이 같은 데이터를 read/write 하는 것을 허용하지 않는다. 

read_lock (shared lock)

read 할 때 사용된다

다른 트랜잭션이 같은 데이터를 read 하는 것은 허용한다

예제3

 

흐름 

x 시작: 10

트랜잭션2: read_lock 획득

트랜잭션1: write_lock 획득 X

트랜잭션2: x read(10)

트랜잭션2: read_lock 반환

트랜잭션1: write_lock 획득

트랜잭션1: x = 20 변경 

트랜잭션1: write_lock 반환

예제4

 

흐름 

x 시작: 10

트랜잭션2: read_lock 획득 

트랜잭션1: read_lock 획득 

트랜잭션1: x read(10)

트랜잭션2: x read(10)

트랜잭션1: read_lock 반환

트랜잭션2: read_lock 반환

Lock 호환성 

  read-lock write-lock
read-lock O X
write-lock X X

 

Lock을 써도 생기는 이상한 현상 예제1

 

트랜잭션1: x에 대한 write_lock, y에 대한 read_lock 필요

트랜잭션2: x에 대한 read_lock, y에 대한 write_lock 필요

 

serial schedule #1

 

트랜잭션1에서 x = 300 y = 200

트랜잭션2에서 x = 300 y = 500

최종적으로 x = 300 y = 500 

 

serial schedule #2

 

트랜잭션2에서 x = 100 y = 300

트랜잭션1에서 x = 400 y = 300

최종적으로 x = 400 y = 300 

 

Nonserializable example

 

현재 schedule에서는 serial schedule에서 나올 수 있는 가능성인 (x=300, y=500) / (x=400, y=300) 과 다르게 x=300, y=300으로 이상한 결과가 나왔다.

 

즉, 락을 사용했어도 이상 현상이 발생했다. 

 

하지만 해당 그림에서 트랜잭션2의 unlock(x) x 락 반환 보다 write_lock(y) 락 획득이 먼저 실행되면 이런 현상이 일어나지 않는다. 

트랜잭션2가 write_lock(y)를 획득하는 순간 트랜잭션1은 read_lock(y)를 획득하지 못해서 블락 상태가 된다.

그래서 트랜잭션2가 y에 대한 락 해지를 해야만 진행이 가능하다.  

2PL protocol (two-phase locking)

현재 그림은 원래의 각 트랜잭션 operations 순서이다. 

실행 순서에 따라 이상 현상이 발생할 수 있음을 우린 예제로 확인했다. 

 

현재 그림은 트랜잭션1에서는 write_lock(x), unlock(y) 순서를 바꾸고 트랜잭션2에서는 write_lock(y)와 unlock(x) 순서를 바꿨다.

 

이렇게 진행하면 이상 현상이 발생하지 않는다. 

현재 그림은 락 획득 / 반환 operations 만 표시한 schedule 이다. 

특징은 모든 락 획득 operations이 최초의 unlock operation 보다 먼저 수행한다는 것이다.

 

이런 방식의 락 프로토콜을 2PL protocol(two-phase locking)이라고 한다. 

2PL protocol은 2단계를 통해 진행한다. 

 

Expanding Phase(Growing Phase)

lock을 취득하기만 하고 반환하지는 않는 phase

 

Shrinking Phase(Contracting Phase)

lock을 반환만 하고 취득하지는 않는 phase

 

2PL protocol은 Serializability를 보장한다. 

2PL protocol & Dead Lock

 

현재 2PL - protocol 사용 

트랜잭션2: x에 대한 read_lock 획득

트랜잭션1: y에 대한 read_lock 획득 

트랜잭션1: x에 대한 write_lock 획득 불가능 

트랜잭션2: y에 대한 write_lock 획득 불가능 

→ dead lock (교착 상태)

 

즉, 2PL 에서는 dead lock 상태가 발생할 수 있다. 

2PL protocol  종류 

해당 예제는 2PL protocol 종류를 이해하기 위한 예제이다.

x에 대해서는 읽기 작업만 필요하니 read_lock y,z에 대해서는 읽기/쓰기 작업이 필요하니 write_lock을 획득한다

 

Conservative 2PL

 

모든 필요한 lock을 취득한 뒤 트랜잭션을 시작

deadlock-free 

실용적이지 않다 (트랜잭션을 시작하기가 어렵다)

 

Strict 2PL (S2PL)

strict schedule을 보장하는 2PL

recoverability 보장

write_lock을 commit / rollback 될 때 반환

 

recoverability & strict schedule 설명 링크

https://20240228.tistory.com/408

 

[MySQL] concurrency control 기초2 (recoverability)

참고 자료 유투브 쉬운코드 동시성 제어 예제schedule 개념과 serializability에 대한 개념이 없으면 이전 글을 참고하자 https://20240228.tistory.com/407 [MySQL] concurrency control 기초1 (schedule, serializability)참

20240228.tistory.com

 

Strong Strict 2PL (SS2PL)

strict schedule을 보장하는 2PL

recoverability 보장

read-lock / write-lock 모두 commit / rollback 될 때 반환 

S2PL 보다 구현이 쉽다 

2PL protocol 단점

read-read를 제외하고는 한 쪽이 block 되니까 전체 처리량이 좋지 않다

그래서 MVCC(Multiversion Concurrency Control)가 등장했다. 

 

초창기 DBMS는 2PL 중에 recoverability를 보장하는 S2PL과 SS2PL을 많이 사용했지만 2PL의 처리량 문제를 비롯한 여러 단점으로 인해 현재는 MVCC를 많이 사용한다.