DBAtlas · 데이터베이스 운영 아틀라스

default 파티션 함정: 새 파티션이 'would be violated by some row'로 실패

PostgreSQL파티셔닝

명령어

-- Which periods have rows in the default partition?
SELECT date_trunc('month', created_at)::date AS month, count(*) AS row_count
FROM sales_default
GROUP BY 1
ORDER BY 1;

-- Move the rows into a new partition and attach it in one transaction
BEGIN;
SET LOCAL lock_timeout = '5s';
LOCK TABLE sales_default IN ACCESS EXCLUSIVE MODE;
CREATE TABLE sales_2027_02 (LIKE sales INCLUDING DEFAULTS INCLUDING CONSTRAINTS);
WITH moved AS (
  DELETE FROM sales_default
  WHERE created_at >= DATE '2027-02-01' AND created_at < DATE '2027-03-01'
  RETURNING *
)
INSERT INTO sales_2027_02 SELECT * FROM moved;
ALTER TABLE sales ATTACH PARTITION sales_2027_02
  FOR VALUES FROM ('2027-02-01') TO ('2027-03-01');
COMMIT;

하는 일

default 파티션에 들어간 행을 기간별로 집계하고, 새 파티션 범위에 속하는 행을 새 테이블로 옮겨 연결하는 작업을 하나의 트랜잭션에서 수행한다.

사용 시점

CREATE TABLE ... PARTITION OF 또는 ATTACH가 'updated partition constraint for default partition would be violated by some row'로 실패할 때, 또는 default 파티션이 커지는 것이 발견될 때.

주의

default 파티션이 있으면 새 파티션을 만들 때마다 default를 전체 스캔하며 그동안 ACCESS EXCLUSIVE를 잡는다. default 파티션이 크면 유지보수 때마다 서비스가 중단된다. 행을 옮기는 동안 default는 쓰기가 막히므로 트래픽이 적을 때 수행한다. 영구 해결: 파티션을 미리 생성하고 모니터링(행 수 > 0이면 알림)으로 default를 비워 두거나, 아예 사용하지 않아 범위를 벗어난 INSERT가 실패하고 문제가 일찍 드러나게 한다. default 파티션은 DETACH ... CONCURRENTLY도 막는다.

DBAtlas에서 열기 →

관련 항목