Django에서 select_for_update() 마스터하기: 경쟁 조건 예방 방법
카테고리
프로그래밍/소프트웨어 개발
서브카테고리
웹 개발
대상자
- Django 웹 개발자, 특히 동시성 문제를 해결해야 하는 중급~고급 개발자
- 데이터 일관성 보장이 필요한 인벤토리 시스템, 결제 시스템, 티켓 판매 시스템 개발자
핵심 요약
select_for_update()
는 트랜잭션 중 데이터베이스 행을 잠그는 ORM 메서드로, 경쟁 조건을 방지합니다.transaction.atomic()
과 함께 사용하여 행 잠금을 강제하고, 재고 관리 등 동시 요청 시 데이터 일관성 보장.nowait=True
또는skip_locked=True
파라미터로 잠금 전략을 맞춤형으로 설정 가능.
섹션별 세부 요약
1. `select_for_update()`의 정의
- 데이터베이스 행을 트랜잭션 종료까지 잠그는 ORM 메서드.
- 다른 트랜잭션이 해당 행을 수정하거나 잠금을 얻을 수 없도록 동기화.
- 인벤토리 시스템, 은행 송금, 티켓 구매, 중복 제출 방지에 유용.
2. 예시: 체크아웃 시 재고 잠금
transaction.atomic()
으로 트랜잭션 시작 →select_for_update()
로 행 잠금.- 재고 수량 검증 후
product.save()
로 변경사항 저장. nowait=True
로 잠금이 이미 있을 경우 예외 발생.skip_locked=True
로 잠긴 행은 전체적으로 스킵 (태스크 큐에 유용).
3. 고급 사용법
nowait=True
: 잠금이 있을 경우 즉시 오류 발생.skip_locked=True
: 잠긴 행은 무시 (태스크 큐, 배치 처리 등에 적합).- 트랜잭션 범위 내에서만 잠금이 유지되며, 트랜잭션 종료 시 자동 해제.
결론
select_for_update()
는 동시성 문제 해결을 위해 데이터베이스 레벨에서 잠금을 강제하는 강력한 도구.transaction.atomic()
과 함께 사용할 때, 재고 관리, 결제 시스템 등에서 데이터 일관성 보장.nowait
및skip_locked
파라미터를 활용해 사용 시나리오에 맞춘 잠금 전략 설계.