낙관적 락, 비관적 락, 네임드 락

2023. 6. 16. 19:25·개발/JPA
반응형

JPA는 데이터베이스 트랜잭션 격리 수준을 READ COMMITTED 정도로 가정한다.

만약 일부 로직에 더 높은 격리 수준이 필요하면 낙관적 락과 비관적 락 중 하나를 사용하면 된다.

 

추가적으로 네임드 락에 대해서도 다시 정리해보겠다.

낙관적 락 (OptimisticLock)

낙관적 락은 이름 그대로 트랜잭션 대부분은 충돌이 발생하지 않는다고 낙관적으로 가정하는 말이다.

DB가 제공하는 락 기능을 사용하는 것이 아니라 JPA가 제공하는 버전 관리 기능을 사용한다.

 

즉 애플리케이션이 제공하는 락이다.

낙관적 락은 트랜잭션을 커밋하기 전까지는 트랜잭션의 충돌을 알 수 없다는 특징이 있다.

충돌이 빈번하지 않을 때 사용하는 것이 좋다.

충돌이 빈번하다면 비관적 락을 사용하는 것이 성능상 이점이 있다.

실패했을 때의 재시도 로직를 개발자가 코드로 작성해야 한다.

 

@Version 애노테이션을 사용해서 구현한다. 

버전은 엔티티의 값을 변경하면 자동으로 증가한다.

 

간단하게 코드를 살펴보자. 아래는 엔티티 클래스다.

@Entity
public class Stock {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    //...기타 코드

    @Version
    private Long version;
 }

다음은 엔티티의 JpaRepository 인터페이스다.

public interface StockRepository extends JpaRepository<Stock, Long> {

    //버전을 활용.
    @Lock(value = LockModeType.OPTIMISTIC)
    @Query("select s from Stock s where s.id = :id")
    Stock findByIdWithOptimisticLock(Long id);
}

낙관적 락의 시나리오는 다음과 같다.

 

  • 사용자 1과 2가 존재하는데 동시에 데이터에 접근한다. 버전은 1이다.
  • 사용자 1이 데이터를 변경하고 변경한 데이터를 커밋하는데, 여기서 버전이 2로 올라간다.
  • 사용자 2가 마찬가지로 데이터를 변경하고 변경한 데이터를 커밋하는데, 현재 데이터의 버전이 2이다.
  • 이러면 사용자 2가 처음에 가져간 데이터 버전 1과 다르기 때문에 데이터를 변경할 수 없다.
  • 그러면 개발자가 작성한 재시도 로직을 타고 다시 데이터 변경을 시도한다.

비관적 락 (PessimisticLock)

이름 그대로 트랜잭션의 충돌이 발생한다고 가정하고 우선 락을 걸고 보는 방법이다.

DB가 제공하는 락 기능을 사용한다. 대표적으로 select for update 구문이 있다.

JPA도 select for update를 사용한다.

 

충돌이 빈번하다면 낙관적 락보다는 비관적 락을 선택해야 한다.

 

다음은 JpaRepository를 사용해서 비관적 락을 구현한 코드다.

public interface StockRepository extends JpaRepository<Stock, Long> {

    //Lock을 걸고 데이터를 가져온다.
    @Lock(value = LockModeType.PESSIMISTIC_WRITE)
    @Query("select s from Stock s where s.id = :id")
    Stock findByIdWithPessimisticLock(Long id);
}

네임드 락(NamedLock)

네임드 락은 GET_LOCK() 함수를 이용해 임의의 문자열에 대해 잠금을 설정할 수 있다.

네임드 락은 단순히 사용자가 지정한 문자열에 대해 획득하고 반납하는 잠금이다.

 

네임드 락은 자주 사용되지 않으며, 보통 분산 락에서 사용한다.

 

예를 들어, 데이터베이스 서버 1대에 5대의 웹 서버가 접속해서 서비스하는 상황에서 5대의 웹 서버가 어떤 정보를 동기화해야 하는 요건처럼 여러 클라이언트가 상호 동기화를 처리해야 할 때 네임드 락을 이용하면 쉽게 해결할 수 있다.

 

웹 애플리케이션에서 네임드 락을 사용하면 네임드 락 DataSource를 분리해야 한다.

커넥션의 수가 부족해질 수 있기 때문이다.

 

다음은 native query를 사용해서 구현한 JpaRepository 예시 인터페이스다.

public interface LockRepository extends JpaRepository<Stock, Long> {

    @Query(value = "select get_lock(:key, 3000)", nativeQuery = true)
    void getLock(String key);

    @Query(value = "select release_lock(:key)", nativeQuery = true)
    void releaseLock(String key);
}

 

참고 자료

자바 ORM 표준 JPA 프로그래밍(김영한)

https://www.inflearn.com/course/%EB%8F%99%EC%8B%9C%EC%84%B1%EC%9D%B4%EC%8A%88-%EC%9E%AC%EA%B3%A0%EC%8B%9C%EC%8A%A4%ED%85%9C/dashboard

 

반응형
'개발/JPA' 카테고리의 다른 글
  • JPA 거짓 연관 관계 맺기(프록시)
  • @Version을 사용하지 않는데 ObjectOptimisticLockingFailureException 등장?!
  • Spring Bean으로 등록된 EntityManager
  • Spring Data JPA 정리
Debin
Debin
공부 기록을 남기며 게시글 리팩토링을 진행하는 블로그입니다.
  • Debin
    리팩토링하는 블로그
    Debin
  • 전체
    오늘
    어제
    • 분류 전체보기
      • DB
        • DB 기초
        • MySQL
        • SQL 튜닝
      • OS
      • Network
      • Git
      • 디지털콘텐츠기획
      • 소프트웨어공학
      • 코딩테스트
        • 프로그래머스
        • 백준
        • 인프런
      • 공부 일지
      • 독서
        • 클린코드
        • 일상 속 사물이 알려주는 웹 API 디자인
        • 토비의 스프링
        • 객체지향의 사실과 오해
        • 자바 잘 읽는 법
      • 기록 및 회고
      • Cloud
        • AWS
      • 개발
        • Java
        • Spring Core
        • Spring MVC
        • Spring DB
        • Spring Boot
        • Spring Security
        • Spring Batch
        • JPA
        • Test
        • Android
      • 대외활동
        • UMC SERVER
        • 카엔프 SW 아카데미
      • 프로젝트
      • Docker
      • Gradle
      • ELK
      • 실무 이야기
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • 깃허브
  • 공지사항

    • 본인 깃허브입니다!
  • 인기 글

  • 태그

    innodb
    AOP
    spring
    docker
    ORM
    JPA
    도커
    컨테이너
    spring boot
    redis
    트랜잭션
    container
    인덱스
    프록시
    객체
    스프링
    Java
    코딩 #개발자 #노마드북클럽 #노개북
    SQL
    mysql
    객체지향
    spring mvc
    리눅스
    test
    스프링 부트
    토비의 스프링
    데이터베이스
    운영체제
    AWS
    자바
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.6
Debin
낙관적 락, 비관적 락, 네임드 락
상단으로

티스토리툴바