ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Lock] 낙관적 락(Optimistic Lock) 이란?
    DB 2024. 1. 22. 16:29

    낙관적 락은 이름 그대로 트랜잭션 충동 상황에 대해 낙관적으로 바라보는 것이다.

    때문에 동시성 문제를 해결하는데 그다지 적합하지 않을 뿐더러, 테이블 구조에 따라 외래키 참조로 데드락이 발생할 수 있다.

    엄밀히 말하자면 DB 레이어의 락이 아닌 애플리케이션 레이어의 락이다.

    실패에 대한 재시도를 개발자가 직접 정의해줘야하며, 실패 후 재시도에 대한 처리는 선착순 이벤트 같은 서비스에는 맞지 않을 수 있다.

    예를들어 100명 중에 50번 째로 신청에 성공했지만 락 경합으로 인해 retry 후 100번 이후로 밀려나 실패한다면 과연 사용자들은 어떻게 받아들일까?

     

    [ 낙관적 락의 작동 원리 ]

    JPA를 사용한다면 라이브러리에 구현된 @Version과 LockModeType.OPTIMISTIC 으로 간단하게 사용할 수 있다.

    이 때 사용되는 버전을 이용한 트랜잭션 제어는 아래를 의미한다.

    update PRODUCT
    set 
        productUniqueId = ?,
        stock = ?,
        ...
        version = version + 1
    where
        productUniqudId = ?,
        version = ? #트랜잭션을 시작한 스레드가 조회한 버전

     

    A, B 트랜잭션 거의 동시에 해당 쿼리를 실행했다고 가정하자.트랜잭션 격리 레벨이 기본 레벨인 REPEATABLE READ 라면 두 트랜잭션 모두 버전을 조회했을 때는1 이었을 것이다.A 트랜잭션이 간발의 차로 먼저 버전의 값을 1에서 2로 수정 했고, B 트랜잭션이 뒤따라 2로 수정했다면 B 트랜잭션은 해당 쿼리를 실패한다.(해당 조건에 맞는 레코드가 없기 때문에)

     

    따라서 동시성 문제가 발생했을 때 쉽게 실패할 수 있지만 실패 후 제어가 쉽지 않기 때문에 근본적인 해결방법이 필요하다.

    예를들면 싱글 스레드라던가 큐 라던가 요청을 일렬로 세울 수 있는 방법 처럼...

     

    [ 낙관적 락의 주의사항 ]

    1. 외래키 변경시 락 전파 주의

    Member - MemberGroup - Group 처럼 1:n:1 관계의 테이블이 있고 MemberGroup이 Group의 id를 fk로 참조하고 있다고 생각해보자.

    MemberGroup 에 insert, update, delete 할 때 Group 테이블의 레코드에 s-lock 이 걸린다.

    그 후 Group 테이블에 레코드를 변경하는 로직을 수행한다면 x-lock 을 걸어야 한다.

    같은 레코드에 s-lock을 건 후 x-lock 을 거는 방법은 여러 트랜잭션이 동시에 접근했을 때 데드락을 발생 시킨다.

    단순 select 를 했더라도 대상이 fk 라면 락을 전파시키므로 주의해야 한다.

     

    2. 안전하지 않고 불편한 락

    낙관적 락은 Mybatis를 사용 중이라면 직접 구현해야하며 락 실패 후 처리를 직접 구현해야하기 때문에 가성비가 좋지 않다.

Designed by Tistory.