원자적 UPDATE는 단일 쿼리로 조건 체크+ 수정을 수행한다. 락 범위는 행 수정 순간만 잡고, 쿼리가 끝난 이후에는 (트랜잭션이 아직 안끝나도) 바로 놓아버린다. 실패시 즉시 반환해버리기 때문에 대기가 거의 없다.
반면 비관 락은 최소 2개 이상의 쿼리를 한다(SELECT+UPDATE). 트랜잭션 종료 전까지 락 대기를 안놓는다.
비관 락을 쓰면 100명이 동시에 요청할 때 99명이 대기해야 하지만 , 원자적 UPDATE는 모두 즉시 처리된다(성공or 실패)
원자적 UPDATE가 적합한 경우는 단순 증감 연산(재고 -1, 좋아요 +1)이 있다. 조건이 단순(remaining >0)하고 선착순 이벤트같은 높은 동시성이 필요할 때 적합하다.
비관 락은 조회 후 복잡한 계산이 필요할 때 쓰인다. 여러 필드를 조건부로 수정하고 다른 테이블과 연계된 로직일 때 적합하다.
<원자적 UPDATE>
DB 내부에서 모든 게 처리됨
┌─────────────────────────┐
│ 락 획득 → 조건체크 → 수정 → 락 해제 │ ← ~1ms
└─────────────────────────┘
<비관적 락 (SELECT FOR UPDATE)>
App ←────────── 네트워크 ──────────→ DB
1. SELECT FOR UPDATE 요청 ─────────→ 락 획득
2. 결과 반환 ←───────────────────── │
3. Java 비즈니스 로직 실행 │ 락 유지 중
4. UPDATE 요청 ───────────────────→ │
5. 커밋 ──────────────────────────→ 락 해제
└──────────── 수십~수백 ms ────────────┘```