DBAtlas · Atlas de operações de banco de dados

Armadilha da partição default: nova partição falha com 'would be violated by some row'

PostgreSQLParticionamento

Comando

-- 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;

O que faz

Conta, por período, as linhas que caíram na partição default; move as linhas dentro do intervalo da nova partição para uma nova tabela e a anexa, tudo em uma única transação.

Quando usar

Quando CREATE TABLE ... PARTITION OF ou ATTACH falha com 'updated partition constraint for default partition would be violated by some row' ou quando se percebe que a partição default está crescendo.

Atenção

Com uma partição default presente, toda nova partição varre a default por completo e mantém ACCESS EXCLUSIVE nela enquanto isso; uma partição default grande significa uma indisponibilidade a cada manutenção. A default fica fechada para gravações enquanto as linhas são movidas; faça isso com tráfego baixo. Correção permanente: crie as partições antecipadamente e mantenha a default vazia com monitoramento (alerta se a contagem de linhas > 0), ou não use uma, para que INSERTs fora do intervalo falhem e o problema apareça cedo. Uma partição default também impede DETACH ... CONCURRENTLY.

Abrir no DBAtlas →

Relacionados