728x90
반응형

데드락이란 무엇인가?

데드락(Deadlock)은 두 개 이상의 프로세스나 스레드가 서로가 가진 자원을 기다리며 무한히 대기하는 상태(=교착상태)

(외나무 다리의 양 끝에서 서로 비켜주기를 바라는 것과 같은 상태)

 

데드락의 발생 조건

데드락이 발생하기 위해서는 다음 네 가지 조건이 동시에 충족되어야 합니다:

  1. 상호 배제(Mutual Exclusion): 자원은 한 번에 하나의 프로세스만 사용할 수 있어야 합니다.
  2. 점유 대기(Hold and Wait): 자원을 가지고 있는 프로세스가 다른 자원을 기다리고 있어야 합니다.
  3. 비선점(No Preemption): 다른 프로세스가 사용 중인 자원을 강제로 빼앗을 수 없어야 합니다.
  4. 순환 대기(Circular Wait): 프로세스들이 순환 형태로 서로의 자원을 기다리고 있어야 합니다.

 

DB에서 발생하는 데드락 예시

-- Transaction A
START TRANSACTION;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
COMMIT;

-- Transaction B
START TRANSACTION;
UPDATE accounts SET balance = balance - 200 WHERE id = 2;
UPDATE accounts SET balance = balance + 200 WHERE id = 1;
COMMIT;

 

이 두 트랜잭션이 다음과 같은 순서로 실행된다고 가정해 봅시다:

  1. Transaction A가 id=1인 계좌의 잠금을 획득합니다.
  2. Transaction B가 id=2인 계좌의 잠금을 획득합니다.
  3. Transaction A가 id=2인 계좌의 잠금을 시도하지만, B가 이미 잠금을 가지고 있어 대기합니다.
  4. Transaction B가 id=1인 계좌의 잠금을 시도하지만, A가 이미 잠금을 가지고 있어 대기합니다.

이 상황에서 두 트랜잭션은 서로가 가진 잠금을 기다리며 영원히 진행하지 못하는 데드락 상태에 빠지게 됩니다.

MySQL은 이러한 데드락을 감지하면 둘 중 하나의 트랜잭션을 강제로 중단시켜 문제를 해결합니다. 하지만 이는 애플리케이션 로직에 예기치 않은 오류를 발생시킬 수 있습니다.

 

데드락을 방지하기 위한 방법

  1. 트랜잭션의 범위를 최소화하여 잠금 시간을 줄입니다.
  2. 모든 트랜잭션이 같은 순서로 테이블에 접근하도록 합니다.
  3. 가능하다면 SELECT ... FOR UPDATE 대신 낙관적 잠금(Optimistic Locking)을 사용합니다.
  4. 트랜잭션 격리 수준을 적절히 조정합니다.

 

결론

데드락은 동시성 프로그래밍에서 흔히 발생할 수 있는 문제입니다. 개발자는 데드락의 발생 조건을 이해하고, 적절한 설계와 프로그래밍 기법을 통해 이를 예방해야 합니다. 특히 데이터베이스 작업에서는 트랜잭션의 설계와 실행 순서에 주의를 기울여야 합니다. 데드락을 완전히 피하는 것은 어렵지만, 그 위험을 최소화하고 발생 시 적절히 대응할 수 있도록 준비하는 것이 중요합니다.

728x90
반응형

+ Recent posts