스냅샷 격리에서 두 당직자가 각각 다른 행을 퇴근 상태로 바꿨더니 당직자가 없어졌습니다. 같은 행 충돌이 없어도 어떻게 규칙이 깨지나요?
잠깐, 답변을 보기 전에
먼저 내 말로 설명해 볼까요?
답변과 점검 포인트 펼치기답변 접기
구두 답변
정의를 외우기보다, 원리와 조건을 연결해 설명해 보세요.
두 요청이 서로 다른 행을 수정해도 함께 읽은 조건에 의존하면 전체 불변식이 깨질 수 있습니다. 이것이 쓰기 편향입니다. 같은 행의 덮어쓰기를 막는 것과 여러 행에 걸친 조건을 직렬화하는 것은 다릅니다.
동작 원리와 전제
A와 B가 모두 당직인 스냅샷에서 각 요청이 다른 당직자가 있다고 보고 자기 행만 false로 바꾸면 쓰기 집합이 겹치지 않습니다. 둘 다 커밋하면 당직자가 0명이 됩니다. 스냅샷 읽기의 일관성만으로 이 결과를 거절하지 않는 격리가 있습니다.
선택과 실패 처리
공통 당직 그룹 행을 잠그고 조건을 재검사하거나, 직렬화 격리로 충돌을 검출해 전체 트랜잭션을 재시도할 수 있습니다. 잠금 범위가 실제 조건을 보호하는지 확인해야 하며 각자 자기 행만 잠그면 해결되지 않습니다. DB 제품과 격리 수준별 동작을 실험하겠습니다.
구체적인 사례와 검증
일반적인 lost update에서는 두 쓰기가 같은 행의 값에서 충돌합니다. 이 예에서는 A행과 B행 각각의 값이 유효해도 '최소 한 명'이라는 집합 조건이 깨집니다. 그래서 최종 검사도 개별 행의 version이 아니라 그룹 내 당직 수를 확인해야 합니다. 명시적 락을 쓴다면 모든 당직 변경 경로가 공통 그룹 락을 지키게 하고, 예외적인 관리자 SQL도 같은 규칙을 통과하게 합니다. 애플리케이션 일부만 보호하면 불변식은 여전히 우회됩니다. 직렬화 실패를 재시도할 때는 새 스냅샷에서 퇴근 가능 여부를 다시 판단하므로 두 번째 요청은 이제 거절될 수 있습니다. 이것은 잘못된 오류가 아니라 지켜야 할 조건을 보호한 정상 결과입니다.
두 세션을 읽기 직후 멈췄다가 각각 쓰게 해 재현합니다. 최종 행 수뿐 아니라 커밋·직렬화 실패와 재시도 비용을 확인합니다. 재시도 중 외부 알림을 다시 보내지 않게 하고, 불변식을 단일 조건부 갱신이나 제약으로 표현할 수 있다면 그 구조를 우선 검토합니다.
득점 포인트
이해가 드러나는 지점을 확인해 보세요.
- 핵심 구분: 두 요청이 서로 다른 행을 수정해도 함께 읽은 조건에 의존하면 전체 불변식이 깨질 수 있습니다.
- 선택 조건: 공통 당직 그룹 행을 잠그고 조건을 재검사하거나, 직렬화 격리로 충돌을 검출해 전체 트랜잭션을 재시도할 수 있습니다.
- 검증 기준: 두 세션을 읽기 직후 멈췄다가 각각 쓰게 해 재현합니다.
감점 포인트
놓치기 쉬운 조건과 오해를 짚어 보세요.
- 서로 다른 행을 바꾸면 transaction 간 업무 충돌이 없다고 말한다.
더 파고들 거리
하나 더 질문하며 이해의 범위를 넓혀 보세요.
- 이 판단을 긴 스냅샷 읽기 안에서 한다면 어떤 버전을 보며 정리 비용은 어떻게 늘어나나요?
- 각 요청을 transaction으로 묶어도 읽기와 쓰기 사이의 경쟁이 남는다면 어떤 원자 조건을 추가하나요?
- 여러 자원을 잠그는 순서가 서로 달라졌다면 순환 대기를 어떻게 재현하고 방지하나요?
득점·감점 포인트는 학습용 자기 점검 기준이며, 특정 회사의 실제 채점표가 아닙니다.
원리부터 공부하고 싶다면
답변을 보충하는 개념·예제·슈도코드를 읽어 보세요.