본문 바로가기
영상 후기/데이터베이스

영상 후기 - LOCK을 활용한 concurrency control 기법을 배워봅니다. 2PL(two-phase locking)도 같이 설명드려요~

by 올리브영 2023. 4. 9.
728x90
반응형

movie

  1. 트랜잭션 1번이 시작한다고 하면 write(x=20)으로 x를 20으로 바꿔준다.
    1. write를 하는 과정은 지금은 쉽게 보기 위해서 간단히 표시한거지만, 원래는 단순히 값 하나 바꾸는 것보다 더 복잡한 과정이다.
  2. 만약, 트랜잭션 1번과 2번이 동시에 실행되면 같은 데이터에 대해서 write를 동시에 실행하는 거니까 어쩌면 x에 대한 처리가 깔끔하게 되지 않아서 예상치 못한 동작을 할 수 있다.
  3. 위의 문제는 lock을 사용해서 해결할 수 있다

lock

  • 데이터마다 lock이 있어서 그 데이터를 변경하거나 읽으려면 lock을 취득해야한다. 만약에 lock을 취득하지 못하면 lock을 취득할 때까지 기다려야 한다. 

lock을 사용해서 해결하기

  1. 트랜잭션 1번이 먼저 실행했다면 트랜잭션 1번은 x를 20으로 바꿔주는 것이기 때문에 write_lock(x) 데이터 x에 대해서 write_lock을 획득한다. 
  2. 트랜잭션 2번도 x를 바꿔주는것이기 때문에 write_lock(x)을 획득하려고 한다. 하지만 이미 write_lock(x)은 트랜잭션 1번이 소유하고 있기때문에 트랜잭션 2번은 더이상 진행하지 못하고 트랜잭션 1번의 write_lock(x)풀릴때까지 기다려야 한다.
  3. 트랜잭션 1번은 계속해서 진행하게 된다. 그래서 x= 20으로 바꾼다.그리고 나서 unlock(x)을 해서 lock을 해지한다.
  4. 그리고 나서 lock 획득하려고 기다렸던 트랜잭션2번이 lock을 획득하고 x를 90으로 바꾸고 unlock(x)를 한다.

 

  1. 트랜잭션 1번이 먼저 실행했다고 가정하고 write_lock(x)를 해서 lock을 획득한다.
  2. 트랜잭션 2번은 x를 읽기 위해서 read_lock(x) 획득하려고 시도하려고 하는데, 이미 트랜잭션 1번이 lock을 획득해서 기다려야한다.
  3. 트랜잭션 1번은 계속 진행해서 x를 20으로 바꾸고, unlock(x)해준다.
  4. 트랜잭션 2번은 lock을 취득하고 x를 읽는다.

write-lock(exclusive lock)

  • read / write(insert, modify, delete)할 때 사용한다.
  • 다른 트랜잭션이 같은 데이터를 read/write 하는 것을 허용하지 않는다.

read-lock(shared lock)

  • read 할때 사용한다.
  • 다른 트랜잭션이 같은 데이터를 read하는 것을 허용한다.
  • 안전하게 데이터를 읽도록 보호

 

  1. 트랜잭션 2번이 먼저 시작해 read_lock(x) 획득한다.
  2. 트랜잭션 1번이 시작해 write_lock(x)을 하려고 하지만 이밎 트랜잭션 2번이 lock을 획득해서 write_lock(x)하지 못한다.
  3. 트랜잭션 2번은 x를 읽고 unlock(x)을 한다.
  4. 트랜잭션 1번은 lock을 획득하고 write(x=20)해서 unlock(x)을 한다.

  1. 트랜잭션 2번이 먼저 시작해 read_lock(x) 획득한다.
  2. 트랜잭션 1번도 read_lock(x)도 획득할 수 있다.
  3. 그러면 둘다 데이터를 x를 읽을 수 있다. 서로 영향을 주지 않기 때문에
  4. 그리고 둘다 같이 unlock(x)을 한다.

lock 호환성

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

lock을 써도 생기는 이상한 현상 예제 - lock을 써도 트랜잭션의 serializable을 보장할 수 없다.

트랜잭션 1 동작 방식

  1. read_lock(y)
  2. read(y)
  3. unlock(y)
  4. write_lock(x)
  5. read(x)
  6. write(x=x+y)
  7. unlock(x)

트랜잭션 2 동작 방식

  1. read_lock(x)
  2. read(x)
  3. unlock(x)
  4. write_lock(y)
  5. read(y)
  6. write(y=x+y)
  7. unlock(y)

두 개의 트랜잭션에 대해서 serial schedule한다면?

  1. serial schedule #1 : t1 -> t2
    1. x=300 y=500
  2. serial schedule #2 : t2 -> t1
    1. x=400, y=300

두 개의 트랜잭션이 섞어서 실행된다면?

  1. 트랜잭션 2번이 먼저 실행했을 때 read_lock(x)가 실행된다. lock 획득
  2. x의 값을 읽는다. read(x) -> 100
  3. unlock(x)
  4. 트랜잭션 1번이 실행해서 read_lock(y)가 실행된다. lock 획득
  5. 트랜잭션 2번이 이어서 진행되면서 write_lock(y)하려고 한다. 그러나 트랜잭션이 1번이 먼저 lock을 획득해서 기다려야한다.
  6. 트랜잭션 1번이 read(y) = 200을 읽을 후 unlock(y)를 한다.
  7. 트랜잭션 2번이 lock을 획득하고 y의 값을 읽는다. 그리고 나서 write(y=300)을 하게된다.(DB 반영) unlock(y)를 한다.
  8. 트랜잭션 1번은 write_lock(x) 획득하고 read(x) = 100해서 x값을 읽고 x에 값을 더해서 write(x=300)을 하게된다.
  9. DB에 x=300이 되고 unlock(x)를 한다.
  10. 최종적으로 x=300, y=300이된다.
    1. 그러나 serial schedule #1과 #2의 결과와 다르다 그래서 해당 스케줄은 Nonserializable이다.
    2. 두개의 트랜잭션이 겹쳐서 실행되어서 이상한 현상이 발생. lock을 사용하는 것만으로는 serializable하지 않을 수 있다라는 것을 알 수 있다.

 

이상한 현상 해결하기


2PL Protocal - Serializability 보장

  • 트랜잭션에서 모든 locking operation이 최초의 unlock operation보다 먼저 수행되도록 하는 것
  • lock을 취득하기만 하고 반환하지는 않는 phase
  • lock을 반환만 하고 취득하지는 않는 phase


  1. 트랜잭션 2번이 먼저 실행되면서 read_lock(x) 획득한다.
  2. 트랜잭션 1번은 read_lock(y)하면서 y lock 획득
  3. 트랜잭션 1번은 y의 값을 읽고, write_lock(x)을 시도한다.
  4. 그러나 트랜잭션 2번이 먼저 x를 획득해서 트랜잭션 1번은 block된 상태로 기다림.
  5. 트랜잭션 2번이 x에 대해 100으로 읽고, write_lock(y)을 하려고 한다. 그러나 획득을 못한다.
  6. 그러면 트랜잭션 1번과 2번 서로 해제 되길 기다리는 상태가 되므로 Deadlock 상태가 된다.

conservative 2PL

  • 모든 lock을 취득한 뒤 트랜잭션을 시작
  • read_lock, write_lock을 맨앞으로 당기는 것.
  • deadlock 발생하지는 않는다.
  • 하지만 실용적이지 않다.

strict 2PL

  • strict schedule을 보장하는 2PL
  • recoverability 보장
  • write-lock을 commit/rollback될 때 반환
728x90
반응형