JPA Transaction 관리(Pessimistic(선점) Lock vs Optimistic(비선점) Lock)

devdo·2022년 7월 28일
0

JPA

목록 보기
11/13
post-thumbnail

DBMS가 지원해주는 트랜잭션 외 JPA에서도 트랜잭션 처리기버을 소개한다.

  • Pessimistic(선점) Lock(잠금): 비관적 잠금
  • Optimistic(비선점) Lock(잠금): 낙관적 잠금

Pessimistic Lock


DDD 참고

  • JPA 프로바이더와 DBMS에 따라 잠금 모드의 구현이 다른데, 하이버네이트의 경우LockModeType.PESSIMISTIC_WRITE 잠금 모드로 사용하면 for update 쿼리를 사용해시 선점 잠금을 구현한다.

  • 교착상태
    선점 잠금 기능을 사용할 때는 잠금 순서에 따른 교착 상태(Deadlock)가 발생할 수 있다.

 1. 스레드1: A 애그리거트에 대한 선점 잠금 구함
 2. 스레드2: B 애그리거트에 대한 선점 잠금 구함
 3. 스레드1: B 애그리거트에 대한 선점 잠금 시도
 4. 스레드2: A 애그리거트에 대한 선점 잠금 시도
  • 이 순서에 따르면 스레드1은 영원히 B 애그리거트에 대한 선점 잠금을 구할 수 없다. ⇒ 스레드2가 B 애그리거트에 대한 잠금을 이미 선점하고 있기 때문이다.
  • 동일한 이유로 스레드2는 A 애그리거트에 대한 잠금을 구할 수 없다. ⇒ 스레드2가 A 애그리거트에 대한 잠금을 이미 선점하였음.
  • 두 스레드는 상대방 스레드가 먼저 선점한 잠금을 구할 수 없어 더 이상 디음 단계를 진행하지 못하며 스레드1과 스레드2는 교착 상태에 빠지게 되는 것이다.
  • 선점 잠금에 따른 교착 상태는 상대적으로 사용자 수가 많을 때 발생할 가능성이 높고, 사용자 수가 많아지면 교착 상태 에 빠지는 스레드가 더 빠르게 증가하게 된다.
  • 이런 문제가 발생하지 않도록 하려면 잠금을 구할 때 최대 대기 시간을 지정해야 한 다. JPA에서 선점 잠금을 시도할 때 최대 대기 시간을 지정하려면 다음과 같이 힌트를 사용하면 된다
Map<String, Object> hints = new HashMap();
hints.put(“javax.persistence.lock.timeout”, 1000);
entityManager.find(Member.class, memberId, LockModeType.PESSIMISTIC_WRITE, hits);
  • JPA의 javax.persistence.lock.timeout 힌트는 잠금을 구하는 대기 시간을 밀리초 단위로 지정한다. 지정한 시간 이내에 잠금을 구하지 못하면 익셉션을 발생시킨다.

  • 힌트를 사용할 때 주의할 점은 DBMS에 따라 힌트가 적용되지 않는다는 것이다. 힌트를 이용할 때에는 사용 중인 DBMS가 관련 기능을 지원하는지 확인해야 한다. (DBMS에 대해 JPA가 어떤 식으로 대기 시간을 처리하는지 반드시 확인)

  • DBMS에 따라 교착 상태에 빠진 커넥션을
    쿼리별로 대기 시간을 지정할 수 있고
    커넥션 단위로만 대기 시간을 지정할 수 있는 DBMS도 있음.


Optimistic Lock

선점 방식에도 단점이 있다. 바로 같은 애거리거트를 수정하는 것이 아니라 특정 애거리거트를 사용하는 부분과 수정하는 부분이 겹치면 문제가 발생한다. 예를 들어보면 사용자의 집 주소를 수정하고 있을 때 배송서비스가 사용자의 집 주소 정보를 가져가서 배송을 한다고 생각해보자. 이 경우 배송이 시작해버리고 사용자 주소는 변경해봐야 소용이 없어진다.

이를 위해서 사용할 수 있는것이 버전 정보이다. 만약 사용자가 정보를 수정하고 있을 때 버전이 9였다. 그리고 사용자 정보를 배송서비스가 접근하면서 버전정보가 10이 되었다. 그 다음 사용자 정보를 수정을 저장하려고 할 때 현재 버전정보가 10이기 때문에 오류가 발생하게 만드는 방식이다.

이는 JPA에서 entity에 @Version 속성만 하나 지정해주면 된다. 그럼 @Transactional 애노테이션을 지정하고 작업을 진행하면 되고 만약 애그리거트의 데이터를 조작하려고 할 때 OptimisticLockingFailureException이 발생하면 이는 버전이 바뀐것이라고 판단하면 된다.



출처

DDD Start 도메인 주도 설계 구현과 핵심 개념 익히기, 최범균 저

profile
배운 것을 기록합니다.

0개의 댓글