Computer Science/데이터베이스

데이터베이스 동시성 제어, 락(LOCK)의개념

콩순이냉장고 2021. 12. 23. 16:09

동시성 제어

동시성 제어 : 트랜잭션이 동시에 수행될때, 일관성을 해지지 않도록 트랜잭션의 데이터 접근을 제어하는 DBMS의 기능을 동시성 제어라고 한다.

 

트랜잭션 읽기/쓰기 시나리오

 

 

갱신손실(lost update) 문제

 

갱신손실는 두개의 트랜잭션이 한개의 데이터를 동시에 갱신(update)할 때 발생한다. 갱신손실 문제는 데이터베이스에서 절대 발생하면 안됨

 

갱신손실이 발생하는경우

A트랜잭션이 X의 계좌에서 100원을 인출하고 

B트랜잭션이 X의 계좌에서 100원을 입금했을때의 예이다 은행에선 당연히 X의 계좌가 1000원이어야 하는데

동시에 X계좌를 접근했을때의 결과를 보여준다

 

트랜잭션 T1 트랜잭션 T2 버퍼 데이터
A= read(X);  (1)
A=A-100;

  X=1000
  B = read(X);    (2)
B=B+100;
X=1000
write(A -> X);      (3)   X=900
  write(B -> X);    (4) X=1100

 

 

문제 발생 :

두 트랜잭션이 종료된후 X값을 보면 110이 됨으로 일관성이 깨짐 

원인을 보자면  (2)에서 X값을 읽어올때 T2는 T1을 갱신준비 중이기에 데이터를 읽어와 중간에 끼어들어 작업을 진행함

그리고 (3)에서 T1이 기록한 데이터를 무시 하고 (4)에서 X값을 갱신 

결과적으로 T2는 잘못된 데이터로 작업하여 잘못된 결과를 만든 다음 T1의 갱신 작업을 무효화하고 덧쓰기 수행하기때문에 갱신손실 문제가 발생되었음

 

 

락은 트랜잭션이 데이터를 읽거나 수정할 때 데이터에 표시하는 장금 장치다.

쉽게 얘끼하면 자신이 사용할 데이터를 락으로 잠그면 다른 트랜잭션은 잠금이 풀릴 때까지 기다려야함

트랜잭션 T1 트랜잭션 T2 버퍼 데이터
LOCK(X)
A= read(X);  (1)

A=A-100;

  X=1000
  LOCK(X)
(wait 대기)
X=1000
write(A -> X);      (2)
UNLOCK(X);
  X=900
  B = read(X);    (3)
B=B+100;
write(B -> X);    (4)
UNLOCK(X)
X=900

 

락의 유형

 

 

트랜잭션이 다루는 데이터의 종류 3가지

  • 읽기만 하는 데이터,
  • 읽고 쓰는 데이터 
  • 쓰기만 하는 데이터가

읽기만 하는 트랜잭션은 어느정도 허용을 해도 문제가 없음 따라서 락의 유형이 2가지가 존재함

 

공유락(LS,shard lock) :트랜잭션이 읽기를 할때 사용하는 락

배타락(LX , exclusive lock) : 트랜잭션이 읽고 쓰기를 할 때 사용하는 락

  • 데이터에 락이 걸려있지 않으면 트랜잭션은 데이터에 락을 걸 수 있다
  • 트랜잭션이 데티어를 X를 읽기만 하면 LS(X)를 요청하고 ,읽거나 쓰기를 하면 LX(X)를 요청한다
  • 다른 트랜잭션이 데이터에 LS(X)을 걸어두면, LS(X)의 요청은 허용하고 LS(X)는 허용하지 않음
  • 다른 트랜잭션이 데이터에 LX(X)을 걸어두면 LS(X)와 LX(X) 모두 허용X
  • 트랜잭션이 락을 허용받지 못하면 대기 상태

 

 

2단계 락킹(phase locking)

 

락을 사용하면 갱신손실 문제를 해결 가능 하지만 락을 걸고 해제하는 시점에서 제한을 두지 않으면 두개의 트랜잭션이 동시에 실행될때 데이터의 일관성이 깨질수 있음  쉽게 얘기해서 데이터에 락을 걸었다 풀고 다시 거는 중간 과정에 락의 해지 상태가 생기면서 다른 트랜젝션에게 중간 겨롹를 보일수 있음

이것을 방지하기위해 2단계 락킹기법을 사용함

 

  • 확장단계(Growing phase, Expanding phase) : 트랜잭션이 필요한 락을 획득하는 단계 , 이단계에선 이미 획득한 락을 해제 하지않음
  • 수축단계(Sharing Phase) : 트랜잭션이 락을 해제하는 단계로 , 이 단계에서는 새로운 락을 획득하지 않음

 

 

트랜잭션 T1,T2가 잇을때 T1은 이체, T2는 이자계산하는 작업을 한다고했을때

초기 A,B 저장된값은 각각 1000원 이다 T1은 A계좌에서 100원을 인출해서 그대로 B계좌에 입금 하여 

T2는 A,B두 계좌의 잔고를 10% 씩 증가한다  T1->T2 혹은 T2->T1 어느 순서를 한다해도 A+B=2200 이됨

 

T1 -> T2일때 A=(1000-100)*1.1 =990 , B=(1000+100)*1.1=1210 이되어 A+B= 2200

T2 -> T1일때 A= 1000*1.1 -100=1000 , B= 1000*1.1 +100 = 1200 이므로 A+B =2200 이된다

결과는 A+B가 2200이 되어야하므로 어떤순서든 상관X 

 

락 사용했지만 문제가 발생하는 경우

트랜잭션 T1 트랜잭션 T2 버퍼 데이터
LX(A)
t1=read(A);
t1=t1-100;
A=write(t1);
UN(A)


  A=900
B=1000
  LX(A)
t2=read(A);
t2=t2*1.1;
A=write(t2);
UN(A)
LX(B)
t2=read(B);
t2=t2*1.1;
B=write(t2);
UN(B)
A=990
B=1100
LX(B)
t1=read(B);
t1=t1+100;
B=write(t1);
UN(B)
  A=990
B=1200
/* A+B=2190이기에 일관성 제약조건 위배 */
     

 

 

해결방법 : 

T1이 A에 락을 걸고 작업을 하다가 중간에 락을 해제 했기에 T2가 A에 접근 가능했기 때문

이문제를 해결하려면 트랜잭션이 작업을 완료하기 전에 는 락을 해제하지 않아야 함 즉

T1이 앞으로 B에 락을 걸 예정이므로  A에 걸었던 락을 미리 해제하면 안됨 2단계 락킹 기법을 사용하여 이 문제를 해결 확장 단계에서는 락을 걸기만하고 , 수축단계에서는 락을 해지하기만 하면 됨

 

트랜잭션 T1 트랜잭션 T2 버퍼 데이터
LX(A)
t1=read(A);
t1=t1-100;
A=write(t1);

  A=900
B=1000
  LX(A) ... 대기상태  
LX(B)
t1=read(B);
t1=t1+100;
B=write(t1);
UN(A)
UN(B)
  A=900
B=1100
  LX(A)
t2=read(A);
t2=t2*1.1;
A=write(t2);
LX(B)

t2=read(B);
t2=t2*1.1;
B=write(t2);
UN(A)
UN(B)
A=990
B=1210
/*
A+B=2200 이므로 일관성 제약조건 지킴
*/

 

 

데드락(Dead Lock)

데드락 : 두개 이상의 트랜잭션이 각각 자신의 데이터에 대하여 락을 획득하고 상대방 데이터에 대하여 락을 요청하면 무한 대기 상태에 빠지는 경우

 

트랜잭션 T1 ,T2 가 있을때 T1은 도서번호가 1인 도서와 도서번호가 2인 도서의 가격을 100원 올리고 , T2는 역순으로

도서번호가 2인 도서와 도서번호가 1인 도서의 가격을 10%인상 할때

 

문제 발생:  T1 bookid가 1인 도서에 락을 걸고 T2는 bookid가 2인 도서에 락을 건다.

T1이 bookid가 2인 도서에 락을 요청하면 대기상태 , 이순간 T2도 bookid가 1인 도서에 락을 요청하여 대기상태가 됨

즉 상대방이 락을 해제하기를 기다리는 무한 대기상태가 빠지기때문에 데드락 상태가 발생함

대기그래프

데드락 해결방법 : 

일반적으로  DBMS T1 혹은 T2의 작업 중 하나를 강제로 중지시킨다 그결과 나머지 트랜잭션은 정상적으로 실행됨 이때 중지시키는 트랜잭션에서 변경한 데이터는 원래 상태로 되돌려 놓음 

예를 들어 T1을 중지했다면 T1이 변경한 도서번호 T1의 가격은 원래상태로 바꿔야함