Replies: 4 comments
-
격리 수준과 이상 현상격리 수준을 결정하는 기준을 이야기하기 전에, 각 격리 수준과 허용되는 이상 현상
트랜잭션 격리 수준이 중요한 이유저는 트랜잭션 격리 수준이 중요한 이유는 결국 단일 요청만 보면 로직이 맞아 보여도, 실제 서비스에서는 같은 데이터를 여러 트랜잭션이 동시에 읽고 수정합니다. 이번 미션 예약 API의 규칙을 예시로 들어볼 수 있을 것 같습니다. 서비스 코드에서는 아래처럼 검증할 수 있습니다. if (reservationRepository.existsByDateAndTimeAndTheme(date, timeId, themeId)) {
throw new IllegalArgumentException("이미 예약된 시간입니다.");
}
reservationRepository.save(reservation);단일 요청만 보면 문제가 없어 보입니다. 즉, 코드상으로는 “중복 예약 방지” 로직이 존재하지만, 그래서 격리 수준은 단순한 DB 옵션이 아니라, 이 API에서 깨지면 안 되는 정합성은 무엇인가?격리 수준을 결정할 때는 저는 먼저 이 질문을 던질 것 같습니다. 예를 들어 단순 조회 API라면 약간 오래된 데이터를 읽는 것이 큰 문제가 아닐 수 있습니다. 반대로 결제, 재고 차감, 예약 생성, 쿠폰 사용, 계좌 이체처럼 이때 선택지는 단순히 “격리 수준을 높인다”만 있는 것은 아니라고 생각합니다.
그래서 저는 격리 수준을 높이는 것은 중요한 선택지이지만, 제 기준으로는 이렇게 정리할 수 있을 것 같습니다. 1. 기본값을 무조건 믿지 않는다DB마다 기본 격리 수준이 다르기 때문에, 2. 읽기 정합성이 중요한지, 쓰기 정합성이 중요한지 구분한다조회 API는 어느 정도 최신성이 떨어져도 괜찮은 경우가 많습니다. 3. 애플리케이션 검증만으로 불변식을 보장하려 하지 않는다서비스 코드의 검증은 사용자에게 좋은 예외 메시지를 주거나, 4. 부하 테스트로 실제 트레이드오프를 확인한다격리 수준이나 락 전략은 이론적으로만 판단하기 어렵다고 생각합니다. 그래서 중요한 API라면 단순히 “이 격리 수준이면 안전하겠지”에서 끝내기보다, 예를 들어 예약 생성 API라면 같은 날짜, 같은 시간, 같은 테마에 대해 동시에 여러 요청을 보내보고,
즉, 격리 수준 결정은 코드와 DB 설정만으로 끝나는 것이 아니라, 최종 정리결론적으로 저는 트랜잭션 격리 수준을 이렇게 이해할 수 있을 것 같습니다. 다만 격리 수준을 무조건 높이는 방향보다는, |
Beta Was this translation helpful? Give feedback.
-
|
모카가 잘 설명해주어서, 비슷한 답변이겠네요
주장에 근거가 없으면 설득력이없습니다. 이때 근거는 단순한 이론이 아니라, 실험을 통해 증명하는 게 효과적이라고 생각합니다.
보다는
가 주변 동료들 그리고 제 자신에게도 설득력있는 의견이라 생각합니다. Q. API를 설계할 때 격리 수준을 명시적으로 고민해보신 적 있으신가요?격리 수준을 고려하는 시기는 대부분 동시성 문제를 맞닿뜨렸을 때이지만, 때문에, API를 설계할 때, 이 부분은 동시성 이슈로 인해 격리수준을 조절해야겠다라고 결정해본 적은 없는 거 같네요. REPEATABLE READ이지만, Phantom Read까지 막아주는 MySQL을 주로 사용해서, 격리수준에 대한 고민을 해본 적이 없는 거 같아요. 그래서 READ COMMITTED, REPEATABLE READ, SERIALIZABLE를 고민하기 보다는, 해당 API가 반드시 지켜야 하는 부분과 느슨해도 되는 부분을 고민해보는 편입니다. 반드시 지켜야하는 부분의 예시는 다음이 있겠습니다.
느슨해도 되는 부분은 다음과 같습니다.
여기서 고민한다는 이유는 비슷한 상황에서도 도메인에 따라, 반드시 지켜야할 수 도 있기 때문입니다. 상황마다 너무 다르기 때문에, 비즈니스 규칙을 나열한 뒤, 가설은 세우고 이를 증명하면서 적절한 선택을 해볼 것 같습니다. |
Beta Was this translation helpful? Give feedback.
-
결론 먼저저는 격리 수준이 높을수록 단순히 더 안전하고 좋다기 보다는, 해당 도메인에서 어떤 데이터 이상현상을 허용할 수 있을지를 기준으로 결정해야 한다고 생각합니다. 즉, 도메인 규칙과 비즈니스 정책에 따라 달라질 것 같습니다. 1. 격리 수준 조정에 앞서 선행되야 할 것사실, 질문의 방향을 조금 벗어나지만, 동시성 제어의 첫번째 옵션으로 격리 수준을 먼저 조정하는 것은 말씀하신대로 트레이드 오프가 크다고 생각합니다. 저는 지금까지 동시성 문제를 해결할 때, 좀더 좁은 범위에서의 락 전략이나 제약 조건을 추가하는 방향으로 동시성을 제어했었습니다. SERIALIZABLE로 올려 정합성을 해결할 수 있겠지만 DB 전체의 동시성 처리 성능에 영향을 주기 때문에 너무 큰 비용의 트레이드 오프가 발생한다고 생각합니다. (물론 송송이 말씀해주신 대로, 이 주장도 실험을 통한 검증을 근거로 삼는다면 더 설득력 있을 것이라고 생각합니다) 따라서 우선은, 격리 수준을 먼저 검토하기 보다, unique constraint, optimistic lock, pessimistic lock 같은 더 좁은 범위의 해결책을 먼저 고려해야 하지 않을까 합니다. 2. 그래도 격리 수준을 조절해야 한다면그럼에도 불구하고, 위와 같은 방법만으로 해결되지 않아 격리수준을 조절해야 한다면, 결국 기준은 도메인 규칙과 비즈니스 정책이 되어야 한다고 생각합니다. 예를 들어, 예약 시스템과 같이 중복 예약이 발생하면 비즈니스 자체에 문제가 생기는 도메인이라면, 성능을 일부 포기하더라도 데이터 정합성을 우선시해야한다고 생각합니다. 반대로 유튜브 조회수처럼 순간적으로 정확한 값이 아니더라도 비즈니스 자체에 큰 문제가 없는 시스템이라면, 읽기 불일치나 읽기 모델의 업데이트에 시간차가 발생하더라도(최종 일관성 보장) 성능을 우선하는 선택도 합리적이라고 생각합니다. |
Beta Was this translation helpful? Give feedback.
-
|
지금까지는 프로젝트에서 격리수준을 따로 설정하여 적용해볼일이 없었는데, 이번 기회에 생각해보게 되었습니다. 먼저 "트랜잭션 격리를 어느 수준으로 설정해야하는가?"에 대한 기준은 간단하게 얘기하자면 하지만 저도 송송님의 의견처럼 동시성 이슈를 마주쳤을 때 트랜잭션의 격리수준을 1차적으로 고려하지는 않는 편인 것 같습니다. 동시성 이슈 해결 방법
적고 보니 저는 동시성 부하가 큰 곳은 아예 DB 바깥으로 빼거나 락 범위를 좁히는 방식으로 풀어왔던 것 같습니다. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
트랜잭션의 격리 수준은 4단계가 존재합니다.
API를 설계할 때 격리 수준을 명시적으로 고민해보신 적 있으신가요?
사용하는 DB마다 기본값도 다르고 개념 자체도 낯설게 느껴질 수 있는데,
막상 실제 동시성 이슈를 마주하고 나서야 뒤늦게 들여다보게 되는 경우가 많은거 같습니다.
격리 수준을 높일수록 정합성은 올라가지만 성능은 떨어집니다.
이러한 트레이드오프를 어떤 기준으로 결정하시나요?
Beta Was this translation helpful? Give feedback.
All reactions