Dead Lock은 서로가 가진 자원을 기다리면서 관련 작업들이 더 이상 진행하지 못하는 상태입니다. 발생하려면 다음 네 가지 필요조건이 모두 성립해야 합니다.
- 상호 배제: 한 자원을 동시에 여러 작업이 사용할 수 없습니다.
- 점유 대기: 자원을 가진 채 다른 자원을 기다립니다.
- 비선점: 보유한 자원을 외부에서 강제로 빼앗을 수 없습니다.
- 순환 대기: 서로의 자원을 기다리는 관계가 고리를 이룹니다.
대응은 예방, 회피, 탐지 및 복구, 무시로 나눕니다.
실무에서는 락 획득 순서를 통일하고, 잠금 범위를 줄이며, 실패 시 안전하게 자원을 해제하는 설계가 중요합니다.
예방과 회피는 어떻게 다른가요?
예방은 락 순서 통일처럼 교착상태의 필요조건이 성립하지 않도록 구조를 제한합니다. 회피는 은행원 알고리즘처럼 최대 자원 요구량 등을 바탕으로 모든 작업이 완료될 수 있는 안전 순서가 유지되는지 확인하며 할당합니다.
대기 관계에 사이클이 있으면 반드시 교착상태인가요?
자원 종류마다 인스턴스가 하나인 자원 할당 그래프에서는 사이클이 교착상태를 의미합니다. 인스턴스가 여러 개라면 다른 작업의 반환으로 대기가 풀릴 수 있어 사이클만으로 확정할 수 없습니다.
타임아웃과 재시도만 넣으면 해결되나요?
타임아웃 뒤에 이미 획득한 자원을 해제하고 작업을 취소·복구할 수 있어야 합니다. 즉시 같은 순서로 재시도하면 충돌이나 라이브락이 반복될 수 있으므로, 획득 순서 통일과 제한된 재시도·백오프를 함께 고려해야 합니다.
InnoDB에서 Deadlock이 발생하면 어떻게 해소하나요?
기본 설정에서는 InnoDB가 트랜잭션의 대기 관계를 검사해 Deadlock을 자동으로 탐지하고, 관련 트랜잭션 중 하나를 롤백하여 순환 대기를 끊고 락을 해제합니다. 롤백된 쪽에는 Deadlock 오류가 반환되므로 애플리케이션은 트랜잭션 전체를 처음부터 안전하게 재시도해야 합니다. Lock Wait Timeout은 단순히 오래 기다린 상황을 처리하는 별도의 메커니즘입니다.
InnoDB는 Deadlock이 발생했을 때 어떤 트랜잭션을 취소하나요?
InnoDB는 롤백 비용을 줄이기 위해 작은 트랜잭션을 희생자로 선택하려고 합니다. 트랜잭션의 크기는 삽입·수정·삭제한 행의 수를 기준으로 판단하므로, 단순히 가장 늦게 시작한 트랜잭션이나 가장 오래 기다린 트랜잭션을 항상 취소하는 것은 아닙니다.