Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BE] refactor: serializable 제거 및 동시성 테스트 추가 #519

Open
wants to merge 8 commits into
base: develop
Choose a base branch
from

Conversation

dongho108
Copy link
Collaborator

@dongho108 dongho108 commented Nov 5, 2022

Issues

논의사항

  • 상황별 동시성 테스트 결과 포함합니다!

동시성 테스트

코드

@Test
@DisplayName("한 코치의 하나의 면담 가능 시간으로 동시에 여러개의 면담을 생성할 수 없다. - 동시성")
void concurrentCreate() throws InterruptedException {
    final int numberOfThreads = 2;
    final ExecutorService service = Executors.newFixedThreadPool(numberOfThreads);
    final CountDownLatch start = new CountDownLatch(numberOfThreads);
    final CountDownLatch end = new CountDownLatch(numberOfThreads);
    coachService.putAvailableDateTimesByCoachId(준.getId(), 면담능시간생성요청정보_2022_07_01_10_TO_12);

    for (long i = 5L; i < 5 + numberOfThreads; i++) {
        final long finalI = i;
        service.execute(() -> {
            try {
                start.countDown();
                start.await();
                interviewService.create(finalI, 면담생성요청정보__2022_07_01_10_00);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                end.countDown();
            }
        });
    }
    end.await();
    final ScheduleResponse response = interviewService.findAllByCoach(준.getId(), 2022, 7);
    assertThat(response.getCalendar()).hasSize(1);
}

1. serializable + not unique

데드락이 발생합니다.

image

innoDB의 serializable은 기본적으로 모든 단순읽기에도 s lock을 걸기때문에

인터뷰가 생성될때

  1. tx1 이 availableDateTime의 레코드를 읽으며 s lock을 걸고
    tx2 가 availableDateTIme의 레코드를 읽으며 s lock을 건다.
  2. tx1이 availableDateTime 을 수정하려고 x lock을 걸때 tx2의 s lock 때문에 기다린다.
    tx2이 availableDateTime 을 수정하려고 x lock을 걸때 tx1의 s lock 때문에 기다린다.

이러한 문제로 데드락이 발생합니다.
-> 틀린 설명

현재 테스트코드는 H2로 돌아가는데 H2 의 serializable은 innoDB처럼 돌아가지 않습니다. (읽기에 slock을 거는 것이 아닙니다)
그럼 데드락이 왜 터질까?

2. repeatable read + not unique

동시성 문제가 발생합니다.

unique가 걸려있지 않기 때문에 2개의 Interview가 동시에 생성이 되었습니다.

image

3. repleatable read + unique

unique 제약조건으로 DB에러가 터집니다.

Caused by: org.h2.jdbc.JdbcSQLIntegrityConstraintViolationException: Unique index or primary key violation: "PUBLIC.UK_89AEH6C8PV4YAQSUYDVIE7QE_INDEX_C ON PUBLIC.INTERVIEW(AVAILABLE_DATE_TIME_ID NULLS FIRST) VALUES ( /* 1 */ CAST(1 AS BIGINT) )"; SQL statement:
insert into interview (id, available_date_time_id, coach_id, crew_id, interview_end_time, interview_start_time, interview_status_type) values (default, ?, ?, ?, ?, ?, ?) [23505-214]

동시에 Interview가 생기지 않기 때문에 이대로 해결하는 방식이 좋아 보입니다.

DB에러이기 때문에 500에러가 터지는데 500 에러로 두는 것과 400에러로 바꾸는 방식중에는 회의를 해봐야할 것 같습니다!

close #510

@github-actions
Copy link

github-actions bot commented Nov 5, 2022

Unit Test Results

0 tests   0 ✔️  0s ⏱️
0 suites  0 💤
0 files    0

Results for commit 47c3e28.

♻️ This comment has been updated with latest results.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[BE] refactor: 트랜잭션 격리레벨 serializable을 제거한다.
2 participants