반응형
Error 3960 – Snapshot Isolation Update Conflict
유형: 일반오류형 · “락이 없는데 왜 실패하지?”를 설명해야 하는 고급 동시성 오류
1️⃣ 대표 오류 메시지
Snapshot isolation transaction aborted due to update conflict
2️⃣ 언제 발생하나
Error 3960은 주로 아래 환경에서 나타납니다.
- SNAPSHOT 격리 수준을 사용하는 트랜잭션
- READ COMMITTED SNAPSHOT (RCSI) 활성화 환경(읽기 동작이 버전 기반)
- 동시에 같은 row(또는 동일 키 범위)를 UPDATE하는 경쟁 상황
현상 특징
- “락 대기”처럼 느려지는 게 아니라
- 락은 거의 없는데
- 어느 순간 트랜잭션이 즉시 Abort(실패)로 떨어짐
- “락 대기”처럼 느려지는 게 아니라
- 락은 거의 없는데
- 어느 순간 트랜잭션이 즉시 Abort(실패)로 떨어짐
3️⃣ 사용자 입장에서 보이는 증상
- 평소엔 잘 되는데 특정 시간대에만 간헐 실패
- UPDATE/저장/확정 버튼에서만 오류 발생
- 재시도하면 성공하는 경우가 많음
- 오류 로그에는 “update conflict”가 찍힘
4️⃣ 왜 이 오류가 고급 장애인가
Error 3960을 제대로 이해하려면
MSSQL의 버전 기반 동작을 알아야 합니다.
MSSQL의 SNAPSHOT 계열은 읽기 일관성을 위해
변경 전 행 버전을 tempdb의 Version Store에 보관하고,
트랜잭션은 “시작 시점의 스냅샷”을 기준으로 읽습니다.
고급 포인트
- “락을 줄이기 위해” 버전 기반으로 읽지만
- “수정(UPDATE)”는 결국 충돌 검사가 필요함
- 충돌하면 기다리지 않고 Optimistic Concurrency 방식으로 실패(Abort)
- “락을 줄이기 위해” 버전 기반으로 읽지만
- “수정(UPDATE)”는 결국 충돌 검사가 필요함
- 충돌하면 기다리지 않고 Optimistic Concurrency 방식으로 실패(Abort)
즉, 이 오류는 “락이 없으니 안전하다”는 오해를 깨는 에러입니다.
MVCC + 낙관적 동시성(Optimistic Concurrency) 모델의 필연적 결과로 발생합니다.
5️⃣ 흔한 오해 (운영에서 자주 나오는 잘못된 결론)
❌ 락 설정 문제
→ 락 때문에 기다리는 문제가 아니라 “버전 기반 충돌로 Abort”되는 문제
→ 락 때문에 기다리는 문제가 아니라 “버전 기반 충돌로 Abort”되는 문제
❌ tempdb 오류
→ Version Store가 tempdb를 쓰긴 하지만, Error 3960은 “tempdb 장애” 메시지가 아님
→ Version Store가 tempdb를 쓰긴 하지만, Error 3960은 “tempdb 장애” 메시지가 아님
❌ 인덱스 문제
→ 인덱스는 성능/범위 경합에 영향을 줄 수 있으나, 핵심은 “동일 row 업데이트 경쟁”으로 인한 충돌
→ 인덱스는 성능/범위 경합에 영향을 줄 수 있으나, 핵심은 “동일 row 업데이트 경쟁”으로 인한 충돌
6️⃣ 운영 환경에서 자주 터지는 구조적 원인
- 핫 로우(Hot Row)
특정 집계 row(카운터/포인트/재고/통계)를 다수 트랜잭션이 동시에 UPDATE - 단일 row 상태값 갱신 경쟁
동일 주문/동일 작업 레코드를 여러 프로세스가 동시에 상태 변경 - 배치와 온라인 트래픽 충돌
배치가 대량 UPDATE하는 동안 온라인 요청이 같은 키를 수정 - 재시도 없는 설계
Snapshot 계열에서 충돌 가능성을 고려하지 않고 “한 번에 성공”을 전제
7️⃣ DBA 레벨 대응 전략
① SNAPSHOT/RCSI를 쓰는 이유 재검토
- “읽기 락 감소”를 위해 켰는지, 단순 권장 설정이라 켰는지 목적 확인
- 업데이트 충돌이 빈번한 워크로드면 이득보다 비용/리스크가 커질 수 있음
- “읽기 락 감소”를 위해 켰는지, 단순 권장 설정이라 켰는지 목적 확인
- 업데이트 충돌이 빈번한 워크로드면 이득보다 비용/리스크가 커질 수 있음
② UPDATE 충돌 가능한 설계 제거
- 핫 로우 분산(샤딩, 파티션, 카운터 분리)
- 상태 전이를 단일 경로로 제한(큐/락 테이블/작업 할당 방식)
- 같은 키를 동시에 잡는 구조를 애초에 줄이는 설계가 핵심
- 핫 로우 분산(샤딩, 파티션, 카운터 분리)
- 상태 전이를 단일 경로로 제한(큐/락 테이블/작업 할당 방식)
- 같은 키를 동시에 잡는 구조를 애초에 줄이는 설계가 핵심
③ Retry 로직 필수(응용단/중간단)
- Error 3960은 “정상적인 동시성 충돌”로 발생 가능
- 즉, 애플리케이션은 반드시 재시도(Backoff 포함) 가능한 구조여야 함
- 재시도 시 “중복 실행 안전성(idempotent)”을 함께 확보
- Error 3960은 “정상적인 동시성 충돌”로 발생 가능
- 즉, 애플리케이션은 반드시 재시도(Backoff 포함) 가능한 구조여야 함
- 재시도 시 “중복 실행 안전성(idempotent)”을 함께 확보
④ tempdb Version Store 모니터링
- Snapshot 계열이 늘수록 tempdb와 version store 부하가 증가
- 장기 트랜잭션이 version store 정리를 막아 급격한 tempdb 사용량 증가로 이어질 수 있음
- “충돌”과 “버전 store 압박”은 함께 관찰해야 함
- Snapshot 계열이 늘수록 tempdb와 version store 부하가 증가
- 장기 트랜잭션이 version store 정리를 막아 급격한 tempdb 사용량 증가로 이어질 수 있음
- “충돌”과 “버전 store 압박”은 함께 관찰해야 함
8️⃣ Oracle ORA-08177과의 관계
👉 성격은 유사: “스냅샷 기반에서 직렬화/동시성 충돌로 트랜잭션 실패”
👉 구현은 다름: MSSQL은 tempdb의 version store 중심, Oracle은 UNDO/일관성 모델 중심
👉 결론은 동일: “락이 적다고 항상 안전한 게 아니며, 재시도·설계 개선이 필수”
👉 구현은 다름: MSSQL은 tempdb의 version store 중심, Oracle은 UNDO/일관성 모델 중심
👉 결론은 동일: “락이 적다고 항상 안전한 게 아니며, 재시도·설계 개선이 필수”
9️⃣ 기본 오류 대응 4단계
1) 환경 확인: SNAPSHOT / RCSI 활성 여부와 해당 트랜잭션 격리 수준 확인
2) 충돌 확인: 어떤 테이블/키에서 update conflict가 발생하는지 식별
3) 단기 대응: 재시도(backoff) 도입 + 충돌 시나리오 완화(동시성 제한)
4) 중장기 개선: 핫 로우 설계 제거 + version store 모니터링 체계 구축
2) 충돌 확인: 어떤 테이블/키에서 update conflict가 발생하는지 식별
3) 단기 대응: 재시도(backoff) 도입 + 충돌 시나리오 완화(동시성 제한)
4) 중장기 개선: 핫 로우 설계 제거 + version store 모니터링 체계 구축
🔟 결론
- Error 3960은 “락이 없는데도 트랜잭션이 실패하는” Snapshot 계열의 대표적 충돌 오류입니다.
- 근본은 MVCC 기반 + 낙관적 동시성 모델의 충돌이며, 단순 설정 변경으로 끝나지 않습니다.
- DBA 관점에서는 “왜 SNAPSHOT을 쓰는가”부터 재검토하고, 충돌 가능 구조 제거와 재시도 안전 설계가 핵심입니다.
- 근본은 MVCC 기반 + 낙관적 동시성 모델의 충돌이며, 단순 설정 변경으로 끝나지 않습니다.
- DBA 관점에서는 “왜 SNAPSHOT을 쓰는가”부터 재검토하고, 충돌 가능 구조 제거와 재시도 안전 설계가 핵심입니다.
이 에러는 “DB가 이상한 것”이 아니라 “동시성 모델이 의도대로 동작한 결과”입니다.
따라서 해결도 “쿼리 한 줄 수정”이 아니라 설계·재시도·모니터링까지 포함한 접근이 필요합니다.
반응형
'지식 공유 > DBMS' 카테고리의 다른 글
| [ORACLE] PLS-00306 조치 절차 (0) | 2025.12.24 |
|---|---|
| [PostgreSQL] PANIC 체크포인트 레코드 오류 (0) | 2025.12.21 |
| [MSSQL] Error 1205 Deadlock Victim (1) | 2025.12.21 |
| [PostgreSQL] 락 트랜잭션 경합 (1) | 2025.12.21 |
| [PostgreSQL] 커넥션 폭주 접속 거부 (0) | 2025.12.21 |
