Search
Duplicate

DB 비관적 락

순서
6
날짜
2024/09/13
사람
상태
Done
태그
DB
이전에 낙관적 락에 작성하였습니다.
낙관적 락을 요약하자면 아래와 같습니다.
데이터를 읽을때 버전 상태를 확인
데이터를 수정할 때 현재 데이터의 버전을 확인합니다. 이때 다른 사용자가 수정하지 않았으면 업데이트가 진행이되고, 버전이 변경되었으면 충돌 난 것으로 확인하고 수정 작업은 실패하고 충돌된 데이터를 해결하기 위해 추가 작업을 애플리케이션에서 진행합니다.
단점
데이터 수정이 많은 로직에는 충돌이 많이 발생하여, 유저의 피로감이 높아져 서비스 유입에 좋지 않은 결과를 초래할 것입니다.
이를 해결하는 방법중 하나로 비관적 락을 사용합니다.

비관적 락(Pessimistic)

모든 트랜잭션이 충돌이 날 것이고, 우선적으로 Lock을 점유하여 접근하지 못하게 하는 방법입니다.
데이터를 수정할 때 x-Lock을 점유하고 있으므로, 충돌이 발생할 가능성이 적습니다.
사용자가 수정할 때 까지 다른 사용자는 스핀락으로 대기를 하고있습니다.
때문에 비관적락 같은경우 Time-out 설정을 통하여, 언제가지 대기를 할 것인지 꼭 지정해 줘야합니다.
비관적 락 경우 next-Lock(갭락)을 사용하기 때문에 갭락이 무엇이고, 어떻게 동작하는 지 알아두면 비관적락을 사용할때 큰 도움이 될 것입니다.
갭락 혹은 next-lock은 레코드 자체에 락을 거는 것 뿐만아니라, 해당 레코드의 앞뒤에 “갭”에도 락을 거는 방식입니다. 이는 트랜잭션이 실행하는 동안 새로운 레코드가 해당하는 범위에 데이터를 삽입되는 것을 방지합니다. [갭락 설명 블로그 : https://idea-sketch.tistory.com/46]
S-Lock이란? Shared Lock 이라고 하고, 다수의 트랜잭션이 동시에 특정 리소스(예: 데이터베이스의 행이나 테이블)를 읽을 수 있도록 허용하는 잠금 메커니즘입니다. 가장 큰 특징으로는 S-Lock이 걸려 있는 동안에는 X-Lock을 획득 할 수 없으며, 수정이 불가능합니다. X-Lock이란? Exclusive Lock 이라 하고, 데이터 베이스에 특정 리소스를 단일 트랜잭션만 접근가능하도록 합니다. X-Lock이 걸린 상태에서는 S-Lock, X-Lock이 접근하지 못합니다.

동시성 테스트

아래 코드는 동시성 테스트를 위한 코드입니다.
동시성 테스트 코드

비관적 락을 사용한 동시성 문제 해결

비관적 락 사용자 1
1.
사용자1 : X-Lock을 획득하여 다른 사용자가 접근하지 못하게 합니다.
2.
사용자2: 스핀락을 통하여 락을 획득할 때 까지 대기합니다.
3.
사용자3: 같은 사유로 락을 획득할때 까지 대기합니다.
4.
사용자4 : 같은 사유로 락을 획득할 때 까지 대기합니다.
사용자 2 락획득
1.
사용자 1: 데이터를 update or insert후 x-lock을 반환합니다.
2.
사용자2: x-lock을 획득하여 update or insert를 진행합니다.
3.
사용자3: 스핀락을 통하여 락을 획득할 때 까지 대기합니다.
4.
사용자4: 같은 사유로 락을 획득 할 때까지 대기합니다.
그렇다면 비관적 락은 왜 사용하는 것일까?
데이터 무결성 보장: 데이터 무결성을 강력하게 보장할 수 있어, 특히 트랜잭션 처리에서 안정성을 높일 수 있습니다.
충돌 방지: 데이터에 락을 설정함으로써, 동시에 발생할 수 있는 데이터 수정 충돌을 효과적으로 방지할 수 있습니다.
비관적 락은 언제 사용하면 좋은가?
여러 사용자가 동시에 같은 데이터를 수정할 가능성이 높은 경우, 예를 들어 은행 시스템의 계좌 이체와 같은 트랜잭션 처리에서 자주 사용됩니다.
데이터의 정확성과 일관성이 매우 중요한 경우
[실습]
JPA에서 비관적 락을 사용하는 방법
public interface ProductRepository extends JpaRepository<ProductEntity, Long> { @Lock(LockModeType.PESSIMISTIC_WRITE) @Query("SELECT p FROM ProductEntity p WHERE p.id = :id") @QueryHints({@QueryHint(name = "javax.persistence.lock.timeout", value = "10000")}) Optional<ProductEntity> findByIdWithPessimisticLock(Long id); }
JavaScript
복사
select for update를 사용하여 X-lock을 획득 하는 것을 볼 수 있습니다.
동시성 또한 문제 없이 통과 한 것을 볼 수있습니다.
final stock : 10
오늘은 비관적 락에 설명하게 되었습니다.
비관적 락을 사용하면서 중요한 점은 timeout 설정을 안하면 락을 획득할 수 때까지 계속 대기해야 되는 상황이 발 생 될 수 있으므로 지정하는게 좋으며, 갭락 next-lock을 생각하여 발생할 수 있는 문제에대해 생각하고 구현해야 됩니다.
다음에는 분산락 에대해 작성하도록 하겠습니다.
비관적 락에서 next-lock에 의해 발생되는 DeadLock 예제