카테고리 없음
TIL 동시성비교 Trouble Shooting
어떻게말이름이히힝
2025. 2. 7. 09:21
프로젝트에서 발생한 문제
저희 프로젝트에서 경험한 문제는 다음과 같습니다:
- 가용 티켓: 3장
- 동시 접근 사용자: 10명
- 예상 결과: 3개의 티켓 발급
- 실제 결과: 9개의 티켓 발급 (오류)
해당 시나리오에서 티켓 발급 시, 위에서 설명한 상황이 발생하였습니다.
Transaction이 완료되기 전에 Lock 이 해제되어, 다른 Thread 들이 아직 커밋되지 않은 데이터를 기반으로 티켓을 발급하여 Dirty Read 가 발생하였습니다.
@Transactional 완료 이전 Lock 해제 시 발생하는 문제
Transaction 완료 이전 Lock 해제 시, Dirty Read 문제가 발생할 수 있습니다.
이는 다음과 같은 상황에서 일어납니다:
- Transaction 이 시작되고 Lock 을 획득합니다.
- 데이터를 수정하지만 아직 커밋하지 않은 상태(Transaction 미완료)입니다.
- Critical section(DB 수정 로직)이 완료되고 unlock 됩니다.
- 다른 Thread 가 Lock 을 획득합니다.
- Lock 을 획득한 Thread 에서 Critical Section 에 진입하여 아직 커밋되지 않은 데이터를 수정합니다. Dirty Read 발생
문제가 발생한 테스트 실행 결과
적용한 해결 방법: Transactional 범위 설정
이 문제를 해결하기 위해 Critical section 을 method 로 분리하여 Lock 내부에서 Transaction 이 완료되도록 설정하였습니다.
@Transactional(propagation = Propagation.REQUIRES_NEW)
public TicketResponseDto sellTicket(Concert concert, User user) {
concert.sellTicket();
concertRepository.save(concert);
Ticket ticket = new Ticket(user, concert);
ticketRepository.save(ticket);
return TicketResponseDto.from(ticket);
}
해당 방법으로 다음과 같이 설정하였습니다.
Transaction 범위의 명확한 지정
- Transaction 을 DB write 작업이 있는 부분에만 적용되도록 설정하여 DB 작업 지점을 명확하게 지정하였습니다.
Lock 해제 시점 제어
- Critical Section 범위를 Transaction 범위보다 넓게 지정하여, Lock 을 Transaction 이후에 해제되도록 설정하였습니다.
위의 두가지 설정으로 Dirty Read 문제를 해결할 수 있었습니다.