본문 바로가기
서비스 웹 서비스 개발 앱 개발 AI 알고리즘 개발 AI 컨설팅 AI 마케팅 프로젝트 인사이트 회사소개 고객게시판
데이터베이스 8 MIN READ

DB 데드락은 장애일까: 짧은 트랜잭션과 안전한 재시도 설계

동시에 여러 업무가 같은 행을 수정하면 데드락이 발생할 수 있습니다. 잠금 순서와 인덱스, 트랜잭션 재시도, 외부 부작용 분리를 실무 기준으로 설명합니다.

Category
데이터베이스
Published
Read
8분
Author
네이처프랙탈
DB 데드락은 장애일까: 짧은 트랜잭션과 안전한 재시도 설계 대표 이미지

주문 A의 재고를 줄이는 작업과 주문 B의 상태를 바꾸는 작업이 동시에 실행됐습니다. 한쪽은 재고 행을 먼저 잠그고 주문 행을 기다립니다. 다른 쪽은 주문 행을 먼저 잠그고 재고 행을 기다립니다. 서로가 가진 잠금이 풀리기만 기다리는 순환이 생기면 데이터베이스는 한 트랜잭션을 취소해야 합니다. 이것이 데드락입니다. 로그에 데드락이 한 번 보였다고 데이터가 망가진 것은 아닙니다. 하지만 이를 무시하거나 무조건 같은 SQL 한 줄만 다시 실행하면 실제 업무 실패가 남을 수 있습니다.

데드락은 왜 정상 코드에서도 생기나

동시 요청이 많아지면 잠금을 얻는 순서가 엇갈릴 수 있습니다. 여러 테이블을 수정하지 않아도 인덱스 레코드와 범위 잠금의 조합으로 발생할 수 있습니다. MySQL InnoDB 문서는 데드락 발생 시 한 트랜잭션을 희생자로 선택해 롤백한다고 설명합니다. 애플리케이션 입장에서는 그 업무가 완료된 것이 아니라 실패 응답을 받은 것입니다. 따라서 실패를 사용자에게 바로 던질지, 안전하게 다시 시도할지 결정해야 합니다.

우선 잠금을 짧게 잡습니다. 사용자 입력을 기다리거나 외부 API를 호출하는 동안 DB 트랜잭션을 열어 두지 않습니다. 필요한 행을 정확한 조건과 인덱스로 찾고, 여러 테이블을 수정한다면 코드 경로마다 같은 순서로 잠그도록 설계합니다. 예컨대 항상 고객 → 주문 → 재고 순서로 접근하면 반대 순서의 순환을 줄일 수 있습니다. 인덱스가 부실해 예상보다 넓은 범위를 잠그는지도 확인해야 합니다.

두 트랜잭션이 서로의 잠금을 기다리는 순환과 하나의 롤백
데드락은 순환 대기이므로 기다리기만 해서는 풀리지 않습니다.

재시도는 SQL 한 줄이 아니라 트랜잭션 전체

희생자로 선택된 트랜잭션은 전체가 롤백됩니다. 마지막 UPDATE만 재실행하면 앞에서 읽고 계산한 상태가 오래된 값일 수 있습니다. 새 트랜잭션을 열어 현재 데이터를 다시 읽고 업무 조건을 다시 판단한 뒤 전체 작업을 수행해야 합니다. 무한 반복은 금물입니다. 제한된 횟수와 짧은 무작위 지연을 두고, 재시도 실패율을 알림으로 보냅니다. MySQL의 데드락 처리 지침도 트랜잭션 재시도를 준비하고 짧은 트랜잭션·일관된 접근 순서를 권합니다.

트랜잭션 안에서 이메일이나 결제 요청을 먼저 보내는 설계는 특히 조심해야 합니다. DB는 롤백됐는데 외부 부작용은 이미 발생했을 수 있기 때문입니다. 외부 호출을 DB 작업과 분리하고 업무 이벤트를 안전하게 전달하는 경로를 마련해야 합니다. 재시도 대상도 구분합니다. 데드락은 재시도 가능한 일시 오류일 수 있지만 유일 제약 위반이나 권한 거부는 같은 입력으로 반복해도 해결되지 않습니다. 오류 코드를 분석해 재시도 정책을 세워야 합니다.

재시도 중에는 사용자에게 두 번 저장된 것처럼 보이지 않게 요청 단위의 결과를 관리합니다. 예를 들어 결재 승인 명령에 업무 요청 ID를 붙여 이미 승인된 같은 요청인지 확인합니다. 다만 데드락이 발생한 트랜잭션은 롤백됐으므로 성공으로 기록해서는 안 됩니다. 성공 응답은 실제 커밋 이후에만 반환해야 합니다. 잠금 대기 시간 초과와 데드락은 서로 다른 오류이므로 로그와 메트릭에서도 분리해 집계하면 어떤 설계 문제가 있는지 더 빨리 찾을 수 있습니다.

빈도와 영향을 함께 측정한다

데드락 로그가 한 건 있었다는 사실보다 어떤 화면·배치에서 얼마나 자주 발생했고, 몇 번의 재시도로 성공했는지가 중요합니다. 실패한 트랜잭션의 유형, 걸린 시간, 관련 테이블과 인덱스를 기록합니다. 마지막 데드락 상황은 SHOW ENGINE INNODB STATUS 등으로 조사할 수 있습니다. 같은 잠금 그래프가 반복된다면 재시도를 늘리기 전에 쿼리 순서와 범위를 바꿔야 합니다. 재시도가 많아질수록 DB 부하가 늘고 다른 요청의 지연까지 악화시킬 수 있습니다.

고정 잠금 순서, 짧은 트랜잭션, 인덱스, 전체 재시도와 계측의 대응 방법
빈도를 낮추는 설계와 실패 시 복구하는 코드가 함께 필요합니다.

테스트 환경에서는 두 트랜잭션이 서로 다른 순서로 같은 자원을 잡게 해 데드락을 재현합니다. 롤백 이후 부분 결과가 남지 않는지, 재시도 성공 시 결과가 한 번만 반영되는지 확인하세요. 데드락은 발생 가능성을 0으로 만들 수 있는 설정값이 아니라, 충돌을 줄이는 트랜잭션 설계와 실패를 되돌리는 복구 코드로 관리하는 운영 현상입니다.

#DB데드락 #InnoDB #MariaDB #트랜잭션 #잠금순서 #데드락재시도 #데이터베이스 #백엔드개발 #동시성 #네이처프랙탈

MariaDB MySQL 품질관리

/ 다음 단계

이런 문제, 직접 겪고 계신가요?

글로 정리한 방법을 실제 환경에 맞춰 적용하는 일까지 함께 하겠습니다.

영업일 기준 3일 이내 회신 · 상담 및 범위 견적 무료