DB Transaction DeadLock

김상진 ·2024년 10월 13일

Problem Solving

목록 보기
1/10

DeadLock(교착상태) 해결 경험

회사에서 작업을 진행하다가 DeadLock(교착상태) 때문에 작업이 실패하는 에러 메시지를 경험했습니다.

상황 설명

상황을 간단하게 설명하자면, A라는 작업은 스케줄러를 통해 주기적으로 스크래핑하여 products의 상태를 관리하는 작업입니다. 반면, B라는 작업은 관리자가 버튼을 클릭하여 OPEN API를 통해 새로운 orders 값을 삽입하는 과정입니다. 이때, orders 테이블에 값을 넣기 위해서는 products의 ID 값을 참조해야 합니다.

B 작업을 진행하기 전에 A 작업이 진행되고 있는지 확인하고 대기하는 방법도 가능하지만, 실제로는 두 작업이 동시에 진행되어야 하는 상황입니다. 예를 들어, A 작업이 주기적으로 데이터 상태를 업데이트해야 하는 한편, B 작업은 관리자의 요청에 따라 즉각적으로 실행되어야 하므로, 두 작업의 동시 실행이 필요합니다.

그런데 이 과정에서 DeadLock이 발생하게 되었고, 이를 해결하기 위해 Redis Lock을 활용한 방법을 적용했습니다.

DataBase에서 Lock이란?

DataBase에서 Lock은 새로운 데이터를 추가하거나 삭제, 수정할 수 없도록 DataBase를 잠그는 것을 이야기합니다. 데이터의 일관성을 유지하고 여러 트랜잭션에서 동시에 데이터를 변경하지 못하도록 하는 것입니다.

DeadLock(교착상태)란?

교착상태(DeadLock)란 두 개 이상의 프로세스가 서로 자원을 점유하고 있으며, 상대방이 보유한 자원을 기다리는 상태를 의미합니다. 이로 인해 각 프로세스는 계속 대기 상태에 빠져 시스템이 멈추게 되는 상황이 발생합니다.

적용한 해결방법

  1. 먼저 제가 맡은 파트는 B 작업입니다. 이 작업은 4~5개의 테이블에 데이터를 삽입해야 합니다. 이에 따라 모든 데이터를 가공해서 모은 뒤, DB 트랜잭션 커밋 주기를 최대한 짧게 설정하여 DeadLock을 줄였습니다. 그러나 간혹 DeadLock이 발생하는 상황이 여전히 있었습니다.

  2. 동시성 제어를 위해 Redis Lock을 사용했습니다. 흐름은 아래와 같습니다:

    1. 작업 A와 작업 B가 실행되기 전에 각각 Lock을 요청합니다.
    2. 작업 A가 Lock을 획득하면 작업을 수행합니다.
    3. 작업 B가 Lock을 요청했을 때, 이미 Lock이 설정되어 있으면 대기합니다.
    4. 작업 A가 완료되면 Lock을 해제하고, 작업 B가 Lock을 획득하여 작업을 수행합니다.
    5. 만약 작업 A가 비정상적으로 종료되면 설정된 Timeout에 의해 Lock이 자동으로 해제됩니다.

이를 통해 DeadLock 문제를 효과적으로 해결하였고, 두 작업의 동시 실행이 가능해졌습니다.

이미지 출처

profile
알고리즘은 백준 허브를 통해 github에 꾸준히 올리고 있습니다.🙂

0개의 댓글