공유 전제

같은 상품 행을 둘이 동시에 수정할 때, 차이는 충돌을 처리하는 시점입니다.

두 방식 모두 데이터 일관성은 지키지만, 하나는 먼저 잠그고 다른 하나는 끝에서 버전을 확인합니다.

현재 재고 10
현재 버전 5
비관적 잠금 먼저 막고 나중에 쓴다 수정 전부터 행 잠금을 잡아 다른 트랜잭션을 기다리게 만듭니다.
낙관적 잠금 먼저 진행하고 끝에서 검증 version 이 그대로일 때만 UPDATE가 성공합니다.
비교 축
비관적 충돌을 미리 차단

대기 시간이 생기지만, 충돌 자체는 앞단에서 줄어듭니다.

낙관적 충돌을 마지막에 검출

읽기 동시성은 좋지만, 늦게 온 쪽은 재시도가 필요할 수 있습니다.

제어 시작
읽은 직후 잠금 획득

다른 트랜잭션이 같은 행을 수정하려면 먼저 기다려야 합니다.

SELECT stock FROM products WHERE id = 1 FOR UPDATE;
UPDATE 순간에 버전 검사

읽을 때는 막지 않고, 쓰기 직전에 내가 본 버전이 아직 유효한지 확인합니다.

UPDATE products SET stock = 9, version = 6 WHERE id = 1 AND version = 5;
동시에 오면
뒤에 온 트랜잭션은 대기
  • Tx A가 행 잠금을 잡고 수정
  • Tx B는 커밋 또는 롤백까지 대기
  • 직렬화에 가까운 흐름으로 충돌을 예방
둘 다 진행, 마지막에 한쪽만 성공
  • Tx A와 Tx B가 모두 version=5 를 읽음
  • 먼저 커밋한 쪽이 version=6 으로 변경
  • 늦은 쪽은 영향 행 0건으로 충돌 감지
잘 맞는 상황
충돌 빈도가 높고 재시도가 비싼 작업

좌석 배정, 재고 마감처럼 같은 행을 자주 두고 경쟁하는 경우에 유리합니다.

충돌이 드물고 읽기 동시성이 중요한 작업

게시글 수정, 설정 변경처럼 대부분은 바로 성공하고 가끔만 재시도해도 되는 경우에 적합합니다.

핵심 선택 비관적 잠금은 기다림을 앞에 두고, 낙관적 잠금은 재검증을 뒤에 둡니다.

즉시 충돌을 막아야 하면 비관적, 대기보다 동시 처리가 더 중요하고 @Version 기반 재시도가 가능하면 낙관적 잠금을 선택합니다.