Skip to content

Latest commit

 

History

History
85 lines (58 loc) · 4.15 KB

File metadata and controls

85 lines (58 loc) · 4.15 KB

Optimistic Locking(낙관적 락) 과 Pessimistic Locking(비관적 락) 에 대해 설명해주세요. 각각의 락을 사용할 상황 또는 제품 사례를 말씀해주세요.

낙관적 락

이름 그대로 데이터 갱신시 충돌이 발생하지 않을 것이라고 낙관적으로 보는 방법입니다. 데이터 갱신시 충돌이 발생하지 않을 것이라고 예상하기 때문에 DB에 락을 걸지 않습니다.

버전을 통해서 관리하고, DB단에 락을 걸지 않기 때문에 어플리케이션 락이라고도 부릅니다.

@Entity
public class OptimisticLockingStudent {
    
    @Id
    private Long id;
    
    private String name;
    
    private String lastName;
    
    @Version
    private Integer version;
}
public void test throws Exception() {
	
    EntityManager em = getEntityManagerWithOpenTransaction();
    OptimisticLockingStudent student = em.find(OptimisticLockingStudent.class, 1L); // Version1
    
    EntityManager em2 = getEntityManagerOpenTransaction();
    OptimisticLockingStudent student2 = em2.find(OptimisticLockingStudent.class, 1L); // Version1
    
    student2.setName("RICHARD");
    em2.persist(student2);
    em2.getTransaction().commit();
    em2.close();
    
    student.setName("John");
    em.persist(student);
    em.getTransaction().commit(); // Version1과 2 충돌. 예외 발생
    em.close();
}

엔티티를 수정할 때 버전이 하나씩 자동으로 증가합니다. ㅇ네티티를 수정할 때 조회 시점의 버전과 수정 시점의 버전이 다르면 예외가 발생합니다. 최초 커밋 이후에는 예외가 발생하게 됩니다.

충돌이 발생하면 오버헤드가 발생합니다. 충돌이나면 롤백 처리는 개발자가 직접 해야 합니다.

ex. 여러 사용자가 상품을 구매해서 동시에 상품 잔여 수량을 수정해야되는 상황에서 낙관적락을 통해 동시 수정을 막을 수 있다.

비관적 락

데이터 갱신시 충돌이 발생할 것이라 보고 잠금을 미리 거는 것입니다. 데이터를 조회할 때 실제 DB에 락을 걸게됩니다. 데이터 무결성을 지키기 좋으나 데드락의 위험성이 있습니다.

비관적 락에는 Shared LockExclusive Lock이 있습니다. Shared Lock은 다른 사용자가 동시에 읽을 수는 있지만 update/delete는 금지입니다. Exclusive Lock은 다른 사용자가 읽기, 수정, 삭제, 모두 불가능한 것입니다.

public interface UserRepository extends JpaRepository<User, Long> {

    @Lock(LockModeType.PESSIMISTIC_WRITE)
    @Query("select b from User b where b.id = :id")
    User findByIdForUpdate(Long id);

}

충돌이 나면 롤백을 DB가 해줍니다.

ex. 롤백을 개발자가 일일이 하는 것이 힘든 경우. 충돌일어났을 때 롤백 비용이 많이 드는 경우. 주문시에 쿠폰 사용, 알람 제공, 주문서 작성, 수량 수정 등 여러 기능이 한 트랜잭션에 엮어있을 때

그래서 언제 뭘 쓸까?

충돌이 자주 발생하지 않으면 optimistic lock을 쓰는게 낫습니다. 하지만 optimistic lock의 오버헤드가 많이 줄어들어서 요즘은 일반적으로 optimistic lock을 많이 쓴다고 합니다.

데이터 성향에따라, 비관적 락이 좋은 경우도 있습니다. -재고가 1개인 상품이 있다. 100만 사용자가 동시적으로 주문을 요청한다.

낙관적 락의 경우 동시 요청을 보낸 사용자가 처리를 순차적으로 하다가 Commit을 하는 시점에 비로소 재고가 없음을 파악하게 된다. 그리고 처리한 만큼 롤백도 해야하기 때문에, 자원 소모도 크게 발생하게 된다.

낙관적 락보다는 DB 트랜잭션 격리 레벨을 Repeatable Read로 하면 되지 않을까?

Repeatable read는 선행 트랜잭션이 종료시까지 다른 트랜잭션이 update, delete하지 못하도록 아예 락을 건다. 반면에 낙관적 락은 애플리케이션 단에서 락을 걸지 않아 트랜잭션 자체를 blocking하지 않으면서도 다른 트랜잭션이 수정하는 것을 막아준다. lock을 거는 것은 성능에 영향을 줄 수 있다.