포스트

Day07 JPA 심화 - 락(낙관적, 비관적)

낙관적 락, 비관적 락

  • JPA에서만 통용되는 개념으로 DB에서는 낙관적락을 직접적인 지원은 없다.

    1. 비관적 락

  • 데이터 접근 시 락을 걸고 데이터를 읽음
  • 읽기/쓰기 락을 통해서 다른 트랜젝션의 접근을 제어한다.
  • 락권한을 가진 트랜잭션이 끝나기 전까지 다른 트랙잭션은 대기 상태에 남는다.

2. 낙관적 락

  • 데이터 접근 시 락을 걸지 않고 데이터를 읽음
  • Version을 통해서 관리를 한다.
  • commit 시점에 version을 비교하여 version이 낮으면 자동 롤백

1) JPA 구현

  • @Version
  • 엔티티가 처음 저장될 때 버전은 0/1로 시작합니다.
  • 엔티티가 수정될 때마다 버전이 자동으로 증가한다.
  • 트랜잭션 충돌 시 OptimisticLockException이 발생한다.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    
      @Entity
      @Builder
      @NoArgsConstructor
      @AllArgsConstructor
      @Setter
      @Getter
      public class Post {
          (...생략...)
          // 추가
          @Version
          private Long version;
      }
    
  • controller
    1
    2
    3
    4
    
      @GetMapping("/modify/optimistic/{id}")
      public Post modifyOptimistic(@PathVariable Long id) {
          return postService.modifyOptimistic(id);
      }
    
  • service
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
      @SneakyThrows
      @Transactional
      public Post modifyOptimistic(Long id) {
          Post post = postRepository.findById(id).orElseThrow();
    
          Thread.sleep(10_000);
    
          post.setUsername(post.getUsername() + "!");
          return post;
      }   
    
  • GET http://localhost:8080/posts/modify/optimistic/1 요청을 날리면서
  • SQL쿼리(DBeaver)를 통해 버전을 인위적으로 수정한다.
  • 10초가 지나면 Get요청을 날린 컨트롤러에서 OptimisticLockException을 발생 시킨다.
  • mariadb경우 JpaSystemException / GenericJDBCException가 발생한다.

    image

JUnitTest

  • 실습코드()
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.