-
[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를 사용 중이라면 직접 구현해야하며 락 실패 후 처리를 직접 구현해야하기 때문에 가성비가 좋지 않다.
'DB' 카테고리의 다른 글
[Lock] X-Lock은 순서를 보장할까?(Transaction Scheduling : CATS) (0) 2024.09.12 [Lock] 비관적 락(Pessimistic Lock) 이란? (0) 2024.01.22 [MySQL] 트랜잭션 격리 레벨 REPEATABLE READ와 동시성 (0) 2024.01.21 [MySQL] 트랜잭션 격리레벨 SERIALIZABLE과 데드락 (1) 2024.01.21