참고
동시성 제어
NOTE
DBMS가 다수의 사용자 사이에서 동시에 적용하는 다중 트랜잭션의 상호간섭 작용에서 Database를 보호하는 것을 의미한다.
일관성과 동시성은 서로 반비례한다..
•
동시성 제어 방법
◦
Lock 기능
◦
SET TRANSACTION 명령어
Optimisitc Lock(낙관적 잠금)
NOTE
DB의 Lock을 사용하지 않고 Version관리를 통해 애플리케이션 레벨에서 처리한다!
기존 A가 A+3이되어서 세션2의 Write가 실패한다.
•
대부분의 트랜잭션이 충돌하지 않는다고 가정하는 방법이다.
•
트랜잭션 커밋 전에는 충돌을 알 수 없다.
Pessimistic Lock (비관적 잠금)
NOTE
데이터를 읽는 시점에 Lock을 걸고, 트랜잭션이 완료될 때까지 이를 유지한다!
세션 1에서 이미 작업하고 있으므로, 세션2는 읽지 못한다. (데이터를 읽는 시점 락을건다.)
•
대부분의 트랜잭션이 충돌한다고 가정하는 방법이다.
•
SELECT 시점에 Lock을 거는 비관적 잠금은 동시성을 심각하게 떨어트릴 수 있어 wait나 nowait 옵션과 사용해야 한다.
Locking 메커니즘의 문제점
NOTE
•
읽기 작업과 쓰기 작업이 서로 방해를 일으키기 때문에 동시성 문제가 발생
•
데이터 일관성에 문제가 생기는 경우도 있어서 Lock을 더 오래 유지하거나 테이블 레벨의 Lock을 사용해야 하고, 동시성 저하가 발생한다.
⇒ 이러한 문제점을 해결하기 위해 MVCC(다중 버전 동시성 제어)가 탄생하게 되었다!
JPA의 낙관적 락, 비관적 락
NOTE
JPA는 데이터베이스에 대한 동시 접근으로부터 엔티티의 무결성을 유지하기 위해 동시성 메커니즘을 제공한다!
public void likePostByOptimisticLock(Long postId) {
var post = postRepository.findById(postId, false).orElseThrow();
post.incrementLikeCount(); // 좋아요 증가에 대한 동시성문
}
Java
복사
Cmd를 활용해서 2개의 쓰레드로 동시에 진행한다.
•
낙관전 락(Optimistic Lock)
◦
데이터 갱신 시, 충돌이 발생하지 않을 것이라는 가정하에 진행
•
비관적 락(Pessimistic Lock)
◦
데이터 갱신 시, 충돌이 발생할 것이라는 가정을 두고 진행하는 락 기법
JPA 낙관적 락 구현(@Version 사용)
NOTE
DB의 Lock을 사용하지 않고, Entity의 버전을 통해 동시성을 제어한다!
@Getter
@NoArgsConstructor
@Entity
public class Member {
// Entity 요소 ..
// 낙관적 락 구현
@Version
private Long version;
// ...
}
Java
복사
@Version 애노테이션을 사용해서, 낙관적 락을 쉽게 구현할 수 있다.
1의 likeCount를 멀티쓰레드로 2번 증가시켰는데, 예외가 발생하고 1번만 적용됨
•
Entity가 변경될 떄 마다 version이 하나 씩 증가하며, Entity를 수정할 때 조회한 시점의 version과 일치하지 않으면 예외가 발생한다!
◦
ObjectOptimisticLockingFailureException
•
‘최초 커밋만 인정하기 정책’을 구현할 수 있다!
참고
•
낙관적 락의 LockModeType을 변경할 수 있지만, @Version에 적용이 불가능.
JPA 낙관적/비관적 락 구현(@Lock 사용)
NOTE
@Lock을 이용해서 락을 걸 수 있다!
public interface MemberRepository extends JpaRepository<Member, Long> {
// 비관적/낙관적 락
@Lock(LockModeType.PESSIMISTIC_WRITE)
Optional<Member> findById(Long id);
}
Java
복사
어떤 LockModType을 거는지에 따라 동작이 달라진다.
lock을 걸어서 동시성 문제가 사라짐!
LockModeType의 종류
•
PESSIMISTIC_READ
◦
다른 트랜잭션에서 Read만 가능
•
PESSIMISTIC_WRITE
◦
다른 트랜잭션에서 Read/Write 불가능
•
PESSIMISTIC_FORCE_INCREMENT
◦
다른 트랜잭션에서 Read/Write 불가능, versioning 진행
•
OPTIMISTIC_LOCK
◦
수정시가 아니라, 조회단계부터 version을 체크한다.
•
OPTIMISTIC_FORCE_INCREMENT
◦
version를 수정하지 않아도 커밋시 자동으로 version을 증가시킨다.
낙관적 락 vs 비관적 락
NOTE
낙관적 락
•
장점
◦
리소스 경쟁이 적고 lock으로 인한 성능저하가 적다.
•
단점
◦
충돌 발생 시 처리해야 할 외부 요인이 존재한다.
비관적 락
•
장점
◦
충돌 발생을 미연에 방지하고 데이터의 일관성을 유지할 수 있다.
•
단점
◦
동시 처리 성능 저하 및 교착상태(DeadLock) 발생 가능성이 있다.