작성자 없음
작성자 정보가 삭제된 글입니다.
작성
·
30
0
안녕하세요 선생님들 도움을 요청 하고자 질문글을 올립니다.
멀티 스레드 테스트 중 문제가 발생 했습니다.
서칭을 해보아도 문제 해결을 할 수 없어서 질문 드립니다.
멀티 스레드 모임 참가 테스트를 위해 테스트 코드를 짯습니다.
트랜잭션 어노테이션이 있을 경우 무한 대기에 빠지고 밑의 예외가 발생 합니다.
이상한점은 트랜잭션 어노테이션이 없거나 H2 DB 테스트를 하면 문제가 없습니다.
완성된 테스트도 H2 데이터 베이스는 통과 하지만 MySql 테스트를 하면 똑같이 무한 대기후
예외가 발생합니다. 이유가 뭘까요 ㅠㅠ 힌트라도 주시면 감사합니다.
void joinEventWhenParticipateAtTheSameTimeWithConcurrency() throws Exception {
//given
int taskCount = 5;
ExecutorService executorService = Executors.newFixedThreadPool(5);
CountDownLatch countDownLatch = new CountDownLatch(taskCount);
Event findEvent = executorService.submit(() ->
eventRepository.save(createEvent("테스터", "테스트 모임", 3))).get();
executorService.shutdown();
}
java.util.concurrent.ExecutionException: org.springframework.dao.PessimisticLockingFailureException: could not execute statement
[Lock wait timeout exceeded; try restarting transaction]
Caused by: org.springframework.dao.PessimisticLockingFailureException: could not execute statement [Lock wait timeout exceeded; try restarting transaction]
@DisplayName("5명의 회원이 동시에 최대 인원이 3명인 모임에 참가 할때 3명만 참여 할 수 있다.")
@Test
void joinEventWhenParticipateAtTheSameTimeWithConcurrency() throws Exception {
//given
int taskCount = 5;
ExecutorService executorService = Executors.newFixedThreadPool(5);
CountDownLatch countDownLatch = new CountDownLatch(taskCount);
Event findEvent = executorService.submit(() ->
eventRepository.save(createEvent("테스터", "테스트 모임", 3))).get();
List<User> users = executorService.submit(() -> Stream
.generate(() -> {
User user = createUser("테스터", "testEmail");
userRepository.save(user);
return user;
})
.limit(taskCount)
.toList()).get();
//when
AtomicInteger exceptionCount = new AtomicInteger(0);
for (User user : users) {
executorService.submit(() -> {
try {
eventService.joinEvent(findEvent.getId(), user.getId());
} catch (BusinessException ex) {
exceptionCount.incrementAndGet();
} finally {
countDownLatch.countDown(); // 카운트다운
}
});
}
countDownLatch.await();
Long participateCount = executorService.submit(
() -> userEventRepository.countParticipantByEventId(findEvent.getId())).get();
executorService.shutdown();
//then
assertThat(participateCount).isEqualTo(3);
assertThat(exceptionCount.get()).isEqualTo(2);
}
답변 1
0
안녕하세요, 인프런 AI 인턴입니다.
조희제님, 멀티 스레드 테스트 관련 문제로 고민이 많으신 것 같습니다. 설명해주신 내용을 바탕으로, 문제의 원인에 대해 생각해보겠습니다.
멀티 스레드 환경에서 트랜잭션과 데이터베이스의 잠금 문제는 자주 발생하는 문제 중 하나입니다. 현재 상황에서는 PessimisticLockingFailureException
이 발생하면서 Lock wait timeout exceeded
가 출력되고 있습니다. 이는 트랜잭션이 잠금을 획득하려고 하지만, 다른 트랜잭션 때문에 잠금이 장시간 해제되지 않아 시간이 초과되었음을 의미합니다.
몇 가지 가능한 원인과 해결 방법을 제시해드리겠습니다.
트랜잭션 전파 수준 및 격리 수준 확인:
데드락(deadlock) 가능성 탐지:
SHOW ENGINE INNODB STATUS;
명령을 실행하여 현재 잠금 상황을 확인할 수 있습니다.쿼리 실행 시간 및 데이터베이스 설정 조정:
innodb_lock_wait_timeout
설정을 늘려서 테스트하거나, 테스트 환경을 보다 잘 시뮬레이션할 수 있도록 설정을 조정할 수 있습니다.테스트 데이터베이스 구성 확인:
비관적 잠금 설정 재확인:
PessimisticLockingFailureException
이 발생하므로 비관적 잠금 설정 및 관련 쿼리를 확인하여 불필요한 잠금이 걸리지 않도록 조정할 필요가 있을 수 있습니다.주어진 정보와 가능성을 생각해 보았을 때, 데이터베이스의 잠금 설정 및 트랜잭션 관리가 주요 원인일 가능성이 높습니다. 위의 제안들을 참고하시어 문제를 해결하는 데 도움이 되길 바랍니다. 추가적인 정보나 결과를 알려주시면 보다 구체적으로 도와드리겠습니다. 화이팅입니다!