비관적 락(Pessimistic Lock)과 낙관적 락(Optimistic Lock)

이도형·2025년 12월 18일

DB Lock의 필요성

  • 여러 트랜잭션이 동시에 같은 데이터를 수정할 때 Lost Update, Dirty Write와 같은 문제 발생 가능
  • 누군가가 작업 중일 때, 잠깐 기다리거나 실패해라는 규칙을 강제로 적용

비관적 락 (Pessimistic Lock)

"대부분의 상황에서 데이터 수정 중 충돌이 발생한다"라는 비관적 상황 가정

특징

  • DB 수준에서 물리적으로 Lock을 잡음
  • 무결성이 중요할 때 사용

장점

  • 동시에 같은 데이터를 수정하려는 경쟁 상황에서 충돌을 사전에 차단
  • 무결성정합성 보장이 확실
  • 계좌 이체, 재고 차감 등 금융계에서 "절대로 틀리면 안되는" 상황에 적합

단점

  • Lock을 잡는 동안 다른 트랜잭션이 대기
  • 동시 처리량이 줄고, 응답 지연이 커짐
  • 여러 자원에서 Lock이 얽히면 Deadlock 위험이 있다
    *Deadlock(교착상태) : 두 개 이상 프로세스가 서로 점유하고 있는 자원을 얻기 위해 무한히 대기하는 상태

낙관적 락 (Optimistic Lock)

"대부분의 상황에서 데이터 수정 중 충돌이 발생하지 않는다"라는 낙관적 상황 가정

특징

  • DB의 물리적 Lock이 아닌, 애플리케이션(JPA 등)에서 제공하는 기능
  • version 컬럼 (숫자 or Timestamp)를 두고 조회 및 업데이트에 적용

장점

  • DB 레벨에서 별도 Lock을 오래 잡지 않아, 동시 처리량과 성능이 좋음
  • 버전 비교로 충돌을 감지하여 Deadlock 위험이 낮음

단점

  • 충돌 발생 시 업데이트 실패가 발생 -> 재시도, 사용자 알림, Merge 로직 구현 필요
  • 충돌 빈도가 높으면 재시도 비용으로 인해 실제 성능이 떨어짐

비교

구분비관적 락낙관적 락
기본 가정충돌이 자주 발생충돌이 드물게 발생
방식미리 DB 락을 걸고 충돌을 차단락 없이 진행 후 커밋 시 충돌 감지
구현 위치주로 DB 수준(X-lock, S-lock 등)주로 애플리케이션 + 버전 컬럼
성능동시성 낮고 지연 증가 가능동시성 높지만 충돌 시 재시도 비용 발생
데드락 위험상대적으로 높음매우 낮음
적합한 사례금융 거래, 재고 관리 등게시글, 설정, 일반 업무 데이터 수정 등

예시 (SQL)

비관적 락

-- 비관적 락

-- quantity가 10이라고 가정
BEGIN;
SELECT quantity FROM stock WHERE id = 1 FOR UPDATE;     -- 락 획득
-- 잠시 대기 (재고 확인 로직)
UPDATE stock SET quantity = quantity - 1 WHERE id = 1;  -- quantity=9
COMMIT;  -- 락 해제

BEGIN;
SELECT quantity FROM stock WHERE id = 1 FOR UPDATE;     -- 세션1 락으로 대기
-- 세션1 커밋 후 진행
UPDATE stock SET quantity = quantity - 1 WHERE id = 1;  -- quantity=8
COMMIT;

-- 즉시 실패
SELECT quantity FROM stock WHERE id = 1 FOR UPDATE NOWAIT;

-- 5초 대기 후 실패
SELECT quantity FROM stock WHERE id = 1 FOR UPDATE WAIT 5;

낙관적 락

-- 낙관적 락
CREATE TABLE posts (
    post_id NUMBER PRIMARY KEY,
    content VARCHAR2(1000),
    version NUMBER DEFAULT 0 -- 버전 관리 컬럼
);

SELECT post_id, 
	   content,
       version
  FROM posts
 WHERE post_id = 1;

UPDATE posts 
SET content = 'Modified Content', 
    version = version + 1 -- 성공 시 버전 업그레이드
WHERE post_id = 1 
  AND version = 5; 		  -- 대상 버전 번호를 조건에 넣음

결론

상황에 따라 무결성과 데드락 위험을 잘 고려하여
비관적 락과 낙관적 락을 적절히 사용하자💡

profile
열심히 살고 싶습니다! 일하고 싶습니다 :)

0개의 댓글