Back-End/DB

락에 대하여

Meluu_ 2025. 8. 20. 18:19

흔히 DB에서 동시성 제어를 위해 사용하는 락에 대해서 다시 공부할 필요가 있어

정리하고 이해한다.

 

락은 말 그대로 잠금이다. 

동시성 제어를 위해 사용되며 3가지 종류가 있다.

  • 비관적 락(Pessimistic Lock)
  • 낙관적 락(Optimistic Lock)
  • 분산 락(Distrubuted Lock)

 

비관적 락


DB나 멀티 스레드 환경에서 여러 사용자가 동시에 동일 레코드에 접근할 때 충돌을 방지하기 위해

미리 락을 거는 방식으로, 사실상 의미그대로 잠금을 거는 것이다. 

동시 접근이 많을 경우, 충돌이 많이 일어날 경우 사용한다. 

 

비관적 락 종류

  • Shared Lock(공유 락, S-Lock)
    • 데이터 읽기 시 사용 하는 락
    • 여러 트랜잭션이 동시 공유락 가능 (동시 읽기 허용)
    • 배타 락이 걸리면 동시 접근 불가
  • Exclusive Lock(배타 락, X-Lock)
    • 데이터 쓰기시 사용하는 락
    • 다른 어떤 트랜잭션도 접근 불가 (읽기도 불가)
    • 락 건 트랜잭션만 읽기/쓰기 허용

사용법

SELECT ... FOR UPDATE; -- 배타 락

SELECT ... FOR SHARE; --  공유 락

 

 

낙관적 락


동시 접근이 적고, 충돌이 적게 일어날 경우 사용

db 레코드에 별도의 version 컬럼을 두어 

트랜잭션 시작 시점에서 읽어온 version과 업데이트 시점의 version을 비교하여 

동시성을 제어한다.

 

락을 잡지 않으므로 성능 부담이 적으나 

충돌시 예외가 발생하고 이는 애플리케이션 단에서 수동으로 재시도 혹은 롤백 처리를 해야한다. 

 

 

동작원리

수정이 될 때마다 version이 1씩 상승

조회시 항상 version을 같이 가져오고

업데이트시 where로 조회한 version을 건다.

 

이때 다른 트랜잭션에서 바꿨다면 업데이트 쿼리 결과가 0건 반영으로 반환될 것이다. 

이는 충돌 발생으로 판단되며, 애플리케이션 단에서 재시도 처리를 한다. 

 

재시도 방법

다시 최신 version을 조회해서 업데이트 쿼리를 날린다. 

 

사용법

//JPA
public class Entity {
 //...
 @Version 
 private int version;
}
//MyBatis
<update id="updateStock">
  UPDATE product
  SET stock = #{stock},
      version = version + 1
  WHERE id = #{id}
    AND version = #{version}
</update>

 

 

분산 락


보통 여러 서버 즉, 분산 환경일때 사용하며

여러 서버가  동시에 같은 자원 접근을 막기 위해 사용한다.

 

종류 

Redis의 (Lettuce)스핀락, redisson(pubSub)

myql의 네임드 락

Zookeeper

 

 

여기에 대해서는 필요할때 찾아서 구현해보는 걸로 한다.