해결된 질문
작성
·
562
4
강사님 안녕하세요! 강의 잘 보고 있습니다.
실무에서 애플리케이션에서 데이터를 DB로 저장할때 애플리케이션을 사용하는 사용자가 정해져 있기 때문에 딱히 락에 대해서 고민해 본적이 없었습니다.
그러다가 강의를 보면서 문득 든 생각이 인기있는 쇼핑몰에서 트래픽이 몰려서 특정 상품 구입에 여러명이 동시에 구매 버튼을 눌렀을 때 재고 수를 맞추기 위해서 왠지 락이 필요할 것 같다는 생각이 문득 들었습니다.
하지만 락을 사용하면 성능 이슈가 발생한다고 하셨는데, 그렇지만 재고를 정확하게 관리하려면 필요할 것 같기도 하다는 생각이 들었지만 제기준에서는 실무에서는 트랜잭션도 READ_COMMIT레벨에서만 사용했기 때문에 감이 잘 오지는 않습니다.
혹시 락이 적용된 사례를 한두가지 알려주실 수 없을까요?
엉뚱한 질문이지만 답변해주시면 감사하겠습니다
답변 2
16
안녕하세요. 갓다귀갓장국님^^
여러가지 경우가 있지만, 주문의 예를 들어들이자면,
고객이 주문을 완료하고 나면, 주문의 상태가 접수 대기 상태로 남게 됩니다.
이 접수 대기 상태에서 사장님은 주문을 접수완료 상태로 바꿀 수 있습니다.
그런데 주문 대기 상태에서 고객은 주문을 취소할 수 있습니다.
여기서 고객이 주문을 취소하는 동시에 사장님이 주문을 접수완료 상태로 변경한다면, 미묘한 차이가 발생합니다.
최악의 경우 고객은 주문 취소에 성공하고, 사장님도 주문을 접수완료 해버릴 수 있습니다.
그러면 체크를 하면 되지 않나요? 라고 하지만 바로 거기서 문제가 발생합니다.
사장님이 주문을 접수완료 처리하는 로직입니다.
접수 완료 로직
1. 데이터베이스에서 주문상태를 조회합니다. 결과 : 주문상태=접수대기
2.만약 주문상태가 접수대기라면 로직 진행, 아니면 예외 처리
3. 데이터베이스에 주문 상태를 접수 완료로 처리
이렇게 보면 맞는 것 같지만, 사실 2번과 3번 사이에서 고객이 주문을 취소해버리면 문제가 됩니다.
그래서 1번에서 주문의 상태를 조회할 때 데이터베이스에 주문의 상태를 변경하지 못하도록 락을 걸어버리면 문제가 해결됩니다.
그런데 또 한편으로 생각해보면, 이렇게 정말 동시에 같은 데이터를 변경할 확율은 거의 밀리초 단위로 사장님이 접수하면서 취소해야 하는데, 대부분의 애플리케이션에서는 문제가 발생활 확율이 매우 낮습니다.
락을 거는 것은 요즘 같은 실시간 애플리케이션에서는 여러가지 위험이 많습니다.(데드락 문제 등등)
그래서 각 데이터베이스 특성에 맞는 락 사용 방법을 명확하게 이해하고, 또 락이 걸린 로우를 조회했을 때 어떤 예외가 발생하는지 등등 다양한 테스트를 꼭 해보아야 합니다.
저는 가급적이면 락을 거는 방법은 피하고, 낙관적 락이나, CAS 스타일의 방식, 또는 RDB나 REDIS 등을 사용해서 해당 주문번호를 한번에 한명한 변경할 수 있도록 로직의 입구에서 막는 방법을 선호합니다.
JPA 락에 대한 더 자세한 내용은 JPA책 16장 트랜잭션과 락 부분을 참고해주세요^^
감사합니다.
2