낙관적 락 (Optimisstic Lock)


낙관적 락 (Optimisstic Lock) 이란?

  • 락이 생길 경우가 없다고 낙관할때
  • 어플리케이션 레벨에서 제공하는 Lock 기능을 사용
  • JPA가 제공하는 엔티티의 버전 관리 기능을 사용
  • 트랜잭션 커밋 전에는 트랜잭션 충돌을 알 수 없음

JPA가 제공하는 낙관적 락 옵션(LockModeType)

  • NONE :  엔티티를 수정하는 시점에 버전이 증가함
    (엔티티에 @Version이 있으면 기본으로 적용되는 락 옵션)
  • OPTIMISTIC :  엔티티를 조회하는 시점에 버전이 증가함
    (Dierty Read 와 Non-Repeatable Read를 방지)
  • OPTIMISTIC_FORCE_INCREMENT : 논리적으로 변경되었을 경우도 버전이 증가함
    (자식 엔티티만 변경되도 부모 엔티티의 버젼이 강제 증가)

* Non-Repeatable Read 이란 한 트랜잭션내에서 같은 쿼리를 두 번 수행했을 때, 결과가 다르게 나타나는 현상을 의미함

 

낙관적 락 옵션(LockModeType)  적용 예제

@Repository
public interface UserMasterJpa extends JpaRepository<UserMasterEntity, String> {
    /**
     * JPA가 제공하는 낙관적 락 옵션(LockModeType)
     * LockModeType.NONE <-- Entity 에 @Version 있다면 Default 임
     * LockModeType.OPTIMISTIC
     * LockModeType.OPTIMISTIC_FORCE_INCREMENT
     */
    @Lock(LockModeType.OPTIMISTIC)
    Optional<UserMasterEntity> findByUserId(Long id);
}

 

버젼 명시 예제

public class UserMasterEntity {

    @Id
    @Column(name = "USER_ID", nullable = false, length = 5)
    private String userId;
    
    @Version
    @Column(name = "DATA_VERSION", nullable = true, precision = 0)
    private Integer dataVersion;

}

 

Lock 을 사용함에 따라 발생할 수 있는 예외

  • ObjectOptimisticLockingFailureException
    (트랜잭션 커밋 시점에 버전이 같지 않으면 발생하는 예외)

사용시 주의사항

  • DB-Lock 을 사용하지 않지만 Dead-Lock이 발생할 수 있음
    (x-Lock이 사용될 경우)
  • 롤백(Rolback) 이슈(어플리케이션 단에서 롤백을 수행해야 함)

* Update 쿼리에 사용되는 모든 레코드에 exclusive lock(x-Lock)을 설정한다고 한다

 

락이 생길 경우가 없다고 낙관할때 사용하는게 좋아보임
(충돌이 예상되거나 충돌이 발생했을 때 비용이 많이 들것이라고 판단되는 곳에서는 사용하지 않는 것이 좋음)

+ Recent posts