Foundry
데이터베이스
중급
핵심

낙관적 락 vs 비관적 락

충돌 시 재시도 vs 미리 락 획득

낙관적 락 vs 비관적 락

핵심 차이

[비관적 락 (Pessimistic)]
"충돌이 날 거야" → 미리 잠금

TX1: SELECT ... FOR UPDATE  ← 락 획득
TX2: SELECT ... FOR UPDATE  ← 대기 (블로킹)
TX1: UPDATE → COMMIT        ← 락 해제
TX2: 이제 실행 가능

[낙관적 락 (Optimistic)]
"충돌 안 날 거야" → 나중에 확인

TX1: SELECT (version=1)
TX2: SELECT (version=1)
TX1: UPDATE WHERE version=1 → OK (version=2)
TX2: UPDATE WHERE version=1 → 실패! (이미 2)
→ 재시도 필요

비교

항목비관적 락낙관적 락
방식DB 락 (SELECT FOR UPDATE)버전 체크 (WHERE version=N)
충돌 시대기 (블로킹)실패 → 재시도
성능충돌 많으면 유리충돌 적으면 유리
데드락가능불가능
적합한 경우좌석 예약, 재고 차감게시글 수정, 설정 변경

실무 구현

-- 비관적 락: 재고 차감
BEGIN;
SELECT stock FROM products
  WHERE id = 1 FOR UPDATE;  -- 락!
UPDATE products
  SET stock = stock - 1
  WHERE id = 1;
COMMIT;

-- 낙관적 락: 게시글 수정
UPDATE posts
  SET title = '새 제목',
      version = version + 1
  WHERE id = 1
    AND version = 5;  -- 버전 체크
-- affected_rows = 0이면 충돌!

선택 기준

충돌 빈도 높음 (재고, 좌석)
  → 비관적 락 (대기가 재시도보다 저렴)

충돌 빈도 낮음 (프로필, 설정)
  → 낙관적 락 (락 없이 성능 좋음)

분산 환경 (여러 서버)
  → 낙관적 락 선호 (DB 락 범위 제한)
면접에서 이렇게 나옵니다

Q.낙관적 락과 비관적 락의 차이를 설명해주세요

충돌을 미리 막는지, 나중에 감지하는지가 다릅니다.

항목비관적 락낙관적 락
전제충돌이 자주 난다충돌이 드물다
방법읽을 때부터 잠근다버전을 비교해 갱신 시 확인한다
구현SELECT ... FOR UPDATEversion 컬럼이나 갱신 시각 비교
대기있다. 다른 트랜잭션이 기다린다없다
실패 처리거의 없다충돌 시 재시도하거나 사용자에게 알린다
위험데드락, 대기 누적재시도 폭증

기준은 충돌 빈도입니다. 충돌이 드물면 낙관적이 훨씬 빠르고, 잦으면 재시도 비용이 잠금 대기 비용을 넘습니다.

흔한 실수: 낙관적 락을 "잠금을 안 쓰니 항상 빠르다"고 답하는 것. 갱신하는 순간에는 DB 가 행을 잠급니다. 다른 점은 읽는 동안 잠그지 않는다는 것입니다.

Q.쇼핑몰 재고 차감에 어떤 락 방식이 적합한가요? 이유는?

경쟁 정도에 따라 다릅니다. 하나로 답하면 반쯤 틀립니다.

상황적합한 방식
일반 상품. 초당 주문 0.2건낙관적 락. 충돌이 사실상 없다
한정 판매. 초당 800건이 재고 100개로 몰린다비관적 락이나 원자적 감소

한정 판매에서 낙관적 락을 쓰면 대부분이 충돌해 재시도가 폭증하고, 재시도가 다시 충돌을 키웁니다.

실무에서 자주 쓰는 방법은 조건부 갱신입니다.

UPDATE stock SET qty = qty - 1 WHERE id = ? AND qty > 0
-- 영향받은 행이 0이면 재고 부족

읽고 계산해서 쓰는 것이 아니라 한 문장으로 조건과 갱신을 함께 하므로 경쟁 상태가 생기지 않습니다. 극단적인 경쟁이면 재고를 캐시에서 원자적으로 차감하고 DB 는 나중에 정산하기도 합니다.

흔한 실수: 읽고 확인한 뒤 갱신하는 흐름을 그대로 두고 락만 논하는 것. 문장 하나로 합치는 것이 더 근본적인 해결입니다.

Q.낙관적 락에서 충돌이 발생하면 어떻게 처리하나요?

갱신 시 영향받은 행이 0이면 충돌입니다. 그 다음 처리를 정해야 합니다.

처리언제
자동 재시도읽고 다시 계산해도 결과가 타당할 때. 재고 차감, 카운터
사용자에게 알림사람이 판단해야 할 때. 문서 동시 편집
병합서로 다른 필드를 고쳤다면 합칠 수 있다
마지막 쓰기 우선정확성이 덜 중요한 값. 조회수, 마지막 접속 시각

자동 재시도를 쓸 때는 상한과 대기 시간이 필요합니다.

3회까지, 50ms 100ms 200ms 로 늘려가며
그래도 실패하면 사용자에게 알린다

간격을 늘리는 이유는 같은 간격으로 재시도하면 또 같은 시점에 부딪히기 때문입니다.

흔한 실수: 무한 재시도를 두는 것. 경쟁이 심할 때 서버 부하가 폭증해 상황을 악화시킵니다.

먼저 스스로 답해보고 아래 답변과 견줘보세요. 막히는 부분은 문제로 확인할 수 있어요.

읽었으면 문제로 확인해보세요

데이터베이스 문제를 풀면 틀린 문제가 자동으로 노트에 쌓입니다. 가입 없이 5문제를 먼저 풀어볼 수도 있어요.