콘텐츠 초기화 동시 실행을 막는 PostgreSQL advisory lock
콘텐츠 DB 초기화는 테이블 생성·스키마 보정·정적 시드·notes/courses 업서를 순서대로 묶습니다. 운영자가 버튼을 두 번 누르거나 console replica가 겹치면, 각 단계가 멱등이어도 두 파이프라인이 중간 상태를 서로 읽을 수 있습니다.
목차
콘텐츠 DB 초기화는 테이블 생성·스키마 보정·정적 시드·notes/courses 업서를 순서대로 묶습니다. 운영자가 버튼을 두 번 누르거나 console replica가 겹치면, 각 단계가 멱등이어도 두 파이프라인이 중간 상태를 서로 읽을 수 있습니다.
서버 동시성 계약
POST /api/db/init는 시작 전에 pg_try_advisory_lock을 획득합니다. 이미 다른 세션이 작업 중이면 DB를 더 건드리지 않고 409 INIT_IN_PROGRESS를 반환합니다. lock을 잡은 세션은 전체 callback 동안 유지하고, 성공·실패·예외 뒤 pg_advisory_unlock과 client release를 실행합니다.
운영자에게 보이는 상태
- 첫 요청만 lock을 획득하는지 확인한다.
- 겹친 요청이
409로 끝나고 시드 행을 쓰지 않는지 확인한다. - 성공과 예외 양쪽에서 lock이 해제되는지 확인한다.
UI 버튼 비활성화는 사용성 보조일 뿐 보안·동시성 계약이 아닙니다. 서버가 반환하는 상태를 role=status 영역에 보여 주고, 운영자는 409를 실패 데이터가 아니라 “현재 작업이 끝난 뒤 재시도할 상태”로 안내해야 합니다.
요청 경합 판정표
| 상황 | 서버 행동 | UI 안내 | 재시도 |
|---|---|---|---|
| lock 획득 | 초기화 시작, 단계별 결과 기록 | 진행 중 | 완료 전 금지 |
| lock 사용 중 | 쓰기 없이 409 INIT_IN_PROGRESS |
다른 작업이 진행 중 | 잠시 후 가능 |
| 단계 실패 | rollback, 오류 단계 반환 | 변경하지 못함 | 원인 제거 후 |
| unlock 실패 | 운영 경고 | 재실행 전 상태 확인 | 소유 확인 후 |
SELECT pg_try_advisory_lock($1); -- false면 즉시 409
-- 같은 세션에서 전체 초기화 실행
SELECT pg_advisory_unlock($1); -- finally에서 실행
세션 단위 lock을 잡은 client는 해제 전 pool로 반환하면 안 됩니다. 다른 요청이 같은 세션의 lock 상태를 이어받지 않도록 획득부터 해제까지 같은 client를 보유합니다.
관련 강좌: Expand/Contract와 멱등 백필