jingyulog

JPA Lock 본문

Tech/JPA

JPA Lock

jingyulog 2023. 4. 11. 16:43

JPA가 제공하는 Lock 옵션과 용도

락 모드 타입 설명
낙관적 락 OPTIMISTIC 낙관적 락을 사용한다.
낙관적 락 OPTIMISTIC_FORCE_INCREMENT 낙관적 락 + 버전정보를 강제로 증가한다.
비관적 락 PESSIMISTIC_READ 비관적 락, 읽기 락을 사용한다.
비관적 락 PESSIMISTIC_WRITE 비관적 락, 쓰기 락을 사용한다.
비관적 락 PESSIMISTIC_FORCE_INCREMENT 비관적 락 + 버전 정보를 강제로 증가한다.
기타 NONE 락을 걸지 않는다.
기타 READ JPA 1.0 호환 기능으로 OPTIMISTIC과 동일
기타 WRITE JPA 1.0 호환 기능으로 OPTIMISTIC_FORCE_INCREMENT와 동일

JPA의 낙관적 락 (Optimistic Lock)

낙관적 락은 트랜잭션 충돌이 거의 발생하지 않는다라는 낙관적인 가정에서 동작한다.

낙관적 락의 특징 중 하나는 트랜잭션이 commit 되는 시점에 충돌 여부를 알 수 있다는 것이다. 왜냐하면, 트랜잭션을 커밋하는 시점에 select 혹은 update 쿼리를 보내면서 충돌 여부를 체크하기 때문이다.

LockModeType.OPTIMISTIC

조회한 엔티티가 트랜잭션이 커밋될 때까지 다른 트랜잭션에 의해 변경되지 않음을 보장한다.

JPA의 빈관적 락 (Pessimistic Lock)

비관적 락은 트랜잭션 충돌이 발생한다를 가정하는 락이다.

주로 DB의 "select for update" 쿼리를 이용해 구현한다. 즉, 해당 쿼리가 걸린 row에 접근을 제어하는 방식으로 비관적 락을 적용한다.

또한 row 자체에 Lock 을 걸기 때문에 Version 정보를 사용하지 않는다.

LockModeType.PESSIMISTIC_WRITE

일반적으로 사용하는 비관적 락이다. DB의 "select for update" 쿼리를 이용해 현재 조회하고 있는 row에 lock을 건다.

따라서 현재 조회하고 있는 row의 commit 시점까지 데이터가 변경되지 않음을 보장한다. 즉, Dirty Read, Non Repeatable Read를 보장한다.

LockModeType.PESSIMISTIC_FORCE_INCREMENT

DB에 update 쿼리를 보내 사용하고 있는 row에 Lock을 건다.

또한 비관적 락이지만 Version 정보를 사용해서 연관 엔티티의 버전을 함께 관리해준다.

JPA의 Lock 적용

JPA의 Lock은 트랜잭션이 commit되는 시점에 동작한다. 따라서 @Transactional 어노테이션을 Service 계층에 달고, Repository에 Lock을 걸어두면 정상적으로 JPA Lock이 적용된다.

적용 방법

  • 스프링 데이터 JPA
    • 메서드에 @Lock 어노테이션 설정
  • 순수 JPA
    • EntityManager를 이용한 설정
    • QueryDSL / JPQL 을 이용한 설정