JPA @Version이나 조건부 갱신으로 충돌을 확인하고,
제한된 횟수만 다시 읽어 재시도한다.
잠금 전략은 충돌 빈도와 실패 비용을 같이 보고 고른다
읽기/쓰기 비율만으로 결정하면 놓치는 것이 많습니다. 충돌이 얼마나 자주 나는지, 실패 후 재시도가 쉬운지, 한 번 실패했을 때 업무 손실이 큰지부터 놓고 낙관적 검사, 비관적 잠금, 원자적 갱신, 큐 직렬화를 조합합니다.
의사결정 맵
X축은 충돌 빈도, Y축은 실패 비용이다. 경계가 애매하면 더 짧은 트랜잭션과 더 강한 제약을 먼저 추가한다.
SELECT FOR UPDATE, NOWAIT,
SKIP LOCKED, lock wait timeout으로 대기 시간을
통제한다.
충돌은 드물어도 손실이 크면 stock >= qty 같은
조건과 유니크 제약으로 잘못된 성공을 차단한다.
재고 차감, 정산, 좌석 배정처럼 실패 비용이 큰 흐름은 짧은 비관적 잠금이나 큐 직렬화를 검토한다.
수정 화면을 오래 열어두는 업무는 잠금을 오래 잡지 않는다. 저장 시점에 버전 불일치를 감지하고 새 값을 보여준 뒤 재시도한다.
같은 행을 자주 갱신하면 먼저 잠그고 빨리 끝낸다. 여러 테이블을 잠글 때는 접근 순서를 통일해 데드락을 줄인다.
인덱스가 부실하면 잠금 범위가 커진다. InnoDB의 record/gap/next-key lock, PostgreSQL과 Oracle의 대기 옵션 차이를 확인한다.
이 방식은 낙관/비관 이름보다 “잘못된 성공을 만들지 않는다”는 불변식을 먼저 코드로 표현한다.