UPDATE stock SET qty = qty - 1 WHERE id = ? AND qty >= 1;
DEFERRABLE INITIALLY DEFERRED로 커밋 시점 검사 가능-- insert-or-ignore (멱등): 이미 있으면 건너뜀
INSERT INTO processed(idem_key) VALUES (?) ON CONFLICT (idem_key) DO NOTHING;
-- upsert: 있으면 갱신
INSERT INTO stock(id, qty) VALUES (?, ?) ON CONFLICT (id) DO UPDATE SET qty = EXCLUDED.qty;
-- 누적 upsert
INSERT INTO counter(key, n) VALUES (?, 1)
ON CONFLICT (key) DO UPDATE SET n = counter.n + EXCLUDED.n;
(컬럼) / ON CONSTRAINT 이름 / 부분 인덱스 (컬럼) WHERE .... DO UPDATE는 target 필수, DO NOTHING은 생략 가능counter.n + EXCLUDED.nRETURNING 가능하나, DO NOTHING으로 건너뛴 기존 행은 반환하지 않음INSERT IGNORE — insert-or-ignore. 단 중복키 외 다른 에러까지 경고로 묵살하므로 주의INSERT ... ON DUPLICATE KEY UPDATE ... — upsert. PK·유니크 중 아무거나 걸리면 반응 → 특정 제약 지정 불가REPLACE INTO — delete 후 insert. auto_increment·FK·트리거 부수효과로 upsert 용도엔 부적합WHEN MATCHED/WHEN NOT MATCHED로 복잡한 분기(+DELETE) 가능ON CONFLICT가 우위(MERGE는 동시 INSERT 시 unique 위반 가능) → 단순 동시-안전 upsert는 ON CONFLICT, 복잡 로직은 MERGEDO UPDATE/ON DUPLICATE KEY UPDATE는 갱신 대상 행에 락. REPEATABLE READ 이상에선 동시 갱신 시 직렬화 에러 → 재시도| 갈래 | 기법 | 특징 | 노트 |
|---|---|---|---|
| 비관적 락 | FOR UPDATE / SKIP LOCKED |
잠그고 진행, 직렬화 안전 | locking-reads |
| 낙관적 락 | @Version + 재시도 |
충돌 시 재시도, 고경합 retry storm | (예정) |
| 원자적 쓰기 | 조건부 UPDATE · UNIQUE · upsert | 단일 문장 원자성, 락 최소 | (이 노트) |
| 범위 제약 | exclusion constraint | 구간 겹침 선언적 금지(PG) | exclusion-constraint |