인프런 커뮤니티 질문&답변

훈마로님의 프로필 이미지

작성한 질문수

자바 ORM 표준 JPA 프로그래밍 - 기본편

기본 키 매핑

기본키 전략 max + 1 문의

해결된 질문

작성

·

3.6K

9

안녕하세요 영한님 JPA 책 부터 인프런의 여러 좋은 강의들 항상 잘 듣고 배우고 있습니다.

간혹 기본키를 숫자 형태로 max + 1로 하는 레거시한 프로젝트를 만나는 경우가 있는데요. 이 경우 동시성 이슈 관련하여 JPA에서 어떤 전략을 사용해야하는지 궁금합니다.

(Spring Data JPA 사용 중입니다)

구체적인 예시를 들면

* 사용자 - 식단카드라는 두 개의 테이블이 존재합니다.

* 식단카드에는 card_key, user_id를 복합키로하며 그 외 카드 식단 정보가 있습니다.

* 식단카드 생성시 user_id를 조건으로 검색하여 가장 높은 card_key를 가져와 + 1해서 card_key를 만들어 저장합니다.

이 때 클라이언트 단에서 비동기 처리로 여러 식단카드를 등록하려다보니 먼저 실행된 요청 쓰레드의 트랜잭션이 성공하고, 두번째 실행된 요청 쓰레드가 먼저 실행된 쓰레드랑 같은 최근값을 읽고 + 1해서 커밋하려니 중복된 키 오류가 발생합니다.

제가 시도해본 방법은 여러가지였는데, 모두 잘 안되더라고요.

MariaDB innoDB 엔진 사용하고요. 기본적으로 JPQL을 사용하여 max + 1 값을 가져오는 Repository 인터페이스 메서드 선언

시도 해본 방법

1. @Transactional isolation level을 SERIALIZBLE 로 변경

  * 해결 되지 않음

2. 비관적 락 @Lock(LockModeType.PESSIMISTIC_WRITE)

  * 해결 되지 않음

  * 구글링 찾아보니 기본키 인덱스 이외의 다른 인덱스가 있을 경우 동작하지 않는다고 하는데, 정확한 공식 문서 내용을 찾아볼 수가 없네요.

3. JPQL NATIVE QUERY 사용하고 FOR UPDATE로 LOCK

  * 해결 되지 않음

결국 Spring Retry 연결하여 실패시 계속 재시도하여 들어가게끔 처리는 했는데, 어거지로 해결한 느낌이라 계속 속에 남아있네요 ㅜㅜ

트랜잭션이나 LOCK에 대해서 공부해서 적용해봐도 안되는 이유를 모르겠습니다ㅜㅜ

답변 2

10

김영한님의 프로필 이미지
김영한
지식공유자

안녕하세요. 훈마로님

max+1은 데이터베이스 락으로 해결하기가 어렵습니다.

데이터베이스 락은 특정 row에 락을 거는 것인데, 생각해보면 max+1을 구하는 방식은 특정 row에 락을 걸어서 해결이 되는 것이 아니니까요.

그리고 특정 row를 변경하는 것이 아니라 새로운 row가 추가되는 것이지요.

이런 문제의 해결 방안은 다음과 같습니다.

[별도의 채번 테이블]

별도의 채번 테이블을 만들어서 사용하는 방식으로 문제를 해결해야 합니다. 채번 테이블의 row 값이 변경되기 때문에 문제를 좀 더 쉽게 해결할 수 있습니다. 다만 현재 요구사항을 만족하기는 어려울 수 있습니다.

[분산 락]

좀더 깔끔한 대안은 채번하는 로직 자체를 한번에 하나의 쓰레드만 동작하게 하는 방법입니다.

이 경우 서버가 여러대가 있어도 하나의 쓰레드만 동작해야 하기 때문에, 락을 동기화 하는 방법이 필요합니다. 따라서 분산 락을 사용해야 합니다.

분산 락 관련해서는 다음을 글들을 참고해주세요.

https://woowabros.github.io/experience/2019/05/30/mysql-user-level-lock.html

https://hyperconnect.github.io/2019/11/15/redis-distributed-lock-1.html

[RDB에서 사용할 수 있는 단순한 방법]

별도의 락 테이블을 하나 만들고, 그곳에 유니크 제약조건을 걸어둡니다.

그리고 여기의 경우 max + 1 채번을 한 다음에 락 테이블에 max+1값을 유니크 제약조건이 걸린 컬럼의 값으로 저장합니다.

이렇게 하면 동시에 접근할 경우 두번째 조건은 유니크 제약 조건 때문에 실패합니다. 실패한 경우 n번 정도 retry 하도록 로직을 작성합니다.

도움이 되셨길 바래요.

5

훈마로님의 프로필 이미지
훈마로
질문자

소중한 답변 감사합니다!!

분산 락이 확실히 깔끔해 보이네요. 이런게 있었군요.ㅜㅜ 오늘도 배우고 갑니다. 잘 적용해보겠습니다.