데이터베이스 데드락

Gunjoo Ahn·2022년 7월 31일
0
post-thumbnail

데드락(Deadlock)이란?

두 개 이상의 작업이 서로 상대방의 작업이 끝나기 만을 기다리고 있기 때문에 결과적으로 아무것도 완료되지 못하는 상태를 가리킨다. - wiki

데드락(Deadlock)은 언제 발생하게 될까?

1971년에 E. G. 코프만 교수는 교착상태가 일어나려면 다음과 같은 네 가지 필요 조건을 충족시켜야 함을 보였다.

  1. 상호배제(Mutual exclusion) : 프로세스들이 필요로 하는 자원에 대해 배타적인 통제권을 요구한다. 한 번에 한 프로세스만 해당 자원을 사용할 수 있다.
  2. 점유대기(Hold and wait) : 프로세스가 할당된 자원을 가진 상태에서 다른 자원을 기다린다.
  3. 비선점(No preemption) : 프로세스가 어떤 자원의 사용을 끝낼 때까지 그 자원을 뺏을 수 없다.
  4. 순환대기(Circular wait) : 각 프로세스는 순환적으로 다음 프로세스가 요구하는 자원을 가지고 있다.

Database 에서는?

Database에서는 Database 일관성을 지키기 위하여 데드락이 발생할 수 있는 환경이다. Update 등 정보 수정에 exclusive lock을 통하여 자원을 점유대기하고 상호배제한다. 또한 한번 선점하면 중간에 당장은 안쓰는 자원이라고 다른 transaction에서 뺏지도 못한다. 거기다 transaction끼리 순서가 꼬이면 순환대기에 빠질 수도 있다.

예를 들어, 복수 row update면 데이터를 순서대로 exclusive lock을 걸게 되는데, 문제는 exclusive lock을 걸려는 대상 row들 중 몇개를 다른 transaction에서 exclusive lock이미 잡아 놓은 것이다.

그런데 exclusive lock을 이미 잡아 놓은 transaction의 새로운 update 쿼리가 복수 row update 쿼리가 잡아놓은 row를 수정하려고 하면 바로 데드락이 걸리게 되는 것이다.

transaction1 - update row a
transaction2 - update rows a, b, c, d, e -> wait for transaction1 to free a
transaction1 - update row b -> wait for transaction2 to free b

Deadlock ! - This example is from James

DB 데드락 해결 방법

💊Dirty Read

데이터 정확도가 중요하지 않다면 빠르게 해결하는 방법이 있다. commit되지 않은 데이터에 접근하는 것을 (dirty read) 허용해 버리는 것이다. 정확도를 희생해 상호배제 조건을 완화시키는 것이다.

💊데드락 예방

👉각 transaction이 실행되기 전에 필요한 데이터를 모두 lock을 하고 모두 lock을 하지 못하면 lock 반납하도록 하여 데드락을 예방할 수 있다.

대신 transaction의 병행성을 희생한다. 또 자원을 계속 얻지 못하는 transaction 기아 현상(starvation)이 발생할 수 있다.

Starvation - 어떤 transaction이 무한정 수행되지 않는 현상. 선착 처리(First-come First-served) 큐를 사용하여 해결한다.
First-come First-served - lock 요청 순서에 따라 lock을 걸 수 있도록 한다.

👉LOCK_TIMEOUT 설정을 통하여 데드락을 예방할 수 있다.

lock의 최대 시간을 설정하여 시간이 지나면 lock을 해제하도록 하여 데드락을 예방할 수 있다. 다만, 데드락이 생기는 상황 자체의 근본적인 해결은 아니다.

💊데드락 회피

자원을 할당할 때 time stamp를 사용하여 데드락을 회피한다.

👉Wait-Die

비선점 기법이다. Time stamp가 더 빠른 transaction이 time stamp 느린 transaction이 점유한 자원에 lock을 걸면 기다린다(wait). 그러나 time stamp가 더 느린 transaction이 time stamp가 더 빠른 transaction이 점유한 자원에 lock을 걸면 롤백후 재시도한다(die). 롤백은 여러번 일어날 수 있다.

👉Wound-Wait

선점 기법이다. Time stamp가 더 빠른 transaction은 기다리지 않는다. 만약 time stamp가 더 빠른 transaction이 더 느린 transaction이 점유하 lock을 요청하면, 더 느린 transaction의 lock을 뺏고 롤백시킨(wound)다. 더 느린 transaction이 더 빠른 transaction이 점유한 자원에 lock을 요청하면 기다린다(wait).

💊데드락 빈도를 낮추는 방법

  • 트랜잭션을 자주 커밋한다.
  • 정해진 순서로 테이블에 접근한다.
  • Deadlock 예방을 위한 것이 아닌 읽기 잠금 획득(SELECT ~ FOR UPDATE)의 사용을 피한다.
  • 한 테이블의 복수 행을 복수의 연결해서 순서 없이 갱신하면 교착 상태가 발생하기 쉽다. 이 경우에는 테이블 단위의 잠금을 획득해 갱신을 직렬화하면 동시성이 떨어지지만 교착 상태를 피할 수 있다.

Reference

DB 교착상태 by 비트코기
[Database] 트랜잭션, deadlock by yrkimoffice
Database - 교착상태 문제를 해결하는 방법! by Jae Honey
데이터베이스 교착 상태(Dead Lock) by 안경잡이개발자
트랜잭션 기아 현상(Starvation) by K-Debbugger
62_교착 상태 처리(Deadlock Handling)와 선출 알고리즘(Election Algorithm) by sungwookkang
Wait-Die 그림 출처
Wound-Wait 그림 출처

profile
Backend Developer

0개의 댓글