전체 용어 목록

교착 상태(데드락)

PostgreSQL에서 교착 상태(데드락)란 무엇이며 어떻게 피할 수 있나요?

교착 상태는 두 트랜잭션이 각자 상대방이 보유한 잠금을 기다릴 때 발생합니다. PostgreSQL은 이를 감지해 둘 중 하나를 취소하며, 일관된 순서로 잠금을 획득하면 이를 방지할 수 있습니다.

교착 상태는 잠금 대기의 순환입니다. 트랜잭션 A는 B에게 필요한 잠금을 보유하고, B는 A에게 필요한 잠금을 보유하고 있어 어느 쪽도 진행할 수 없습니다. PostgreSQL은 이러한 순환을 자동으로 감지하고 트랜잭션 중 하나를 중단시켜 해소하며, 중단된 트랜잭션은 deadlock detected 오류를 받습니다.

이 검사는 잠금 대기가 생길 때마다 실행되지는 않습니다. 세션은 먼저 deadlock_timeout(기본값 1초) 동안 기다린 후에 순환을 찾습니다. 가장 좋은 방어책은 모든 트랜잭션에서 같은 객체를 같은 순서로 잠그고(예를 들어 기본 키 순으로 정렬해 행을 잠그는 방식), 트랜잭션을 짧게 유지하는 것입니다. 그래도 교착 상태가 발생할 수 있는 코드는 중단된 트랜잭션을 재시도해야 합니다.

예제

이 예제는 변경할 두 행을 업데이트하기 전에 하나의 문에서 id 순으로 정렬해 모두 잠급니다. 이 행들을 다루는 모든 트랜잭션이 같은 방식을 따르면, 교착 상태에 빠지는 대신 차례대로 기다리게 됩니다.

CREATE TABLE ledger (id int PRIMARY KEY, balance int);
INSERT INTO ledger VALUES (1, 100), (2, 100);

SHOW deadlock_timeout;

BEGIN;
SELECT id FROM ledger WHERE id IN (1, 2) ORDER BY id FOR UPDATE;
UPDATE ledger SET balance = balance - 10 WHERE id = 1;
UPDATE ledger SET balance = balance + 10 WHERE id = 2;
COMMIT;

확장 없이 기본 PostgreSQL 16 또는 17에서 실행되는 일반 SQL입니다. 버려도 되는 빈 데이터베이스에서 실행하세요.

출처

PostgreSQL 공식 문서(영문)입니다.

관련 용어