PostgreSQL 심화 — 트랜잭션·인덱스·JSONB·파티션 · 트랜잭션과 잠금 · 퀴즈
퀴즈: 트랜잭션과 잠금
문항 8개. 정답과 해설은 풀어 본 뒤에 보여 드립니다.
기본 격리 수준(READ COMMITTED)에서 두 세션이 같은 계좌 잔액을 읽어 각각 100을 더해 다시 썼더니, 두 번 입금했는데 잔액은 한 번만 늘었다. 이 현상의 이름과 원인은?
- 갱신 손실 — 둘 다 커밋 전의 같은 값을 읽어 같은 결과를 덮어썼다
- 팬텀 읽기 — 없던 행이 중간에 나타나 집계가 어긋났다
- 더티 읽기 — 커밋되지 않은 값을 읽어 계산했다
- 쓰기 편향 — 서로 다른 행을 읽고 갱신해 제약이 깨졌다
위의 갱신 손실을 막는 방법으로 **적절하지 않은** 것은?
- 잔액을 읽을 때 SELECT ... FOR UPDATE 로 행을 잠근다
- 격리 수준을 REPEATABLE READ 로 올리고 오류 시 재시도한다
- max_connections 를 늘려 동시 처리량을 확보한다
- UPDATE 한 문장에서 balance = balance + 100 으로 계산한다
REPEATABLE READ 트랜잭션 둘이 같은 행을 갱신하려 할 때, 뒤늦게 커밋하려는 쪽이 받는 것은?
- 두 갱신이 모두 반영되어 잔액이 정상적으로 두 번 늘어난다
- 상대 트랜잭션이 커밋할 때까지 무한히 기다렸다가 진행한다
- could not serialize access 오류로 되돌려져 재시도해야 한다
- 커밋된 최신 값으로 자동으로 다시 계산되어 조용히 반영된다
작업 대기열에서 여러 워커가 SELECT ... FOR UPDATE SKIP LOCKED 로 일감을 집는 이유는?
- 잠긴 행에서 오류를 내 워커가 즉시 다른 큐로 옮기게 하려고
- 다른 워커가 잠근 행을 건너뛰고 다음 행을 집어 겹치지 않게 나눠 처리하려고
- 잠긴 행을 자동으로 복제해 두 워커가 함께 처리하려고
- 트랜잭션 없이도 행을 안전하게 바꿀 수 있게 하려고
두 세션이 각각 계좌 A·B 를 반대 순서로 잠그다가 서로를 기다려 멈췄다. PostgreSQL 은 어떻게 하나?
- 두 트랜잭션을 모두 되돌려 안전하게 만든다
- 먼저 시작한 트랜잭션을 항상 살린다
- 교착을 감지해 한쪽을 희생자로 골라 되돌린다
- lock_timeout 이 0이면 둘 다 영원히 멈춰 있는다
advisory lock(예: pg_advisory_lock(42))의 대표적인 쓰임은?
- 특정 행의 갱신을 다른 세션이 못 읽게 막는다
- 테이블 전체에 읽기 잠금을 걸어 백업을 안전하게 한다
- 트랜잭션이 끝날 때 자동으로 커밋을 보장한다
- 같은 배치 작업이 두 번 겹쳐 돌지 않도록 하나만 실행되게 한다
lock_timeout 과 idle_in_transaction_session_timeout 은 각각 무엇을 끊는가?
- 앞은 잠금을 기다리는 시간을, 뒤는 트랜잭션을 연 채 노는 세션을 끊는다
- 앞은 쿼리 전체 실행 시간을, 뒤는 유휴 커넥션을 끊는다
- 둘 다 같은 것을 끊으며 이름만 다르다
- 앞은 유휴 커넥션을, 뒤는 잠금 대기를 끊는다
마이그레이션(ALTER TABLE)에 lock_timeout 을 거는 것이 중요한 이유는?
- DDL 은 롤백할 수 없어 끊을 방법이 그것뿐이라서
- ACCESS EXCLUSIVE 대기가 그 뒤의 읽기 요청까지 전부 줄 세우기 때문
- 잠금을 오래 쥐면 WAL 이 재활용되지 않아 디스크가 차기 때문
- 대기 중인 DDL 이 교착으로 감지되지 않아 영원히 남기 때문