DBAtlas · Atlas de operaciones de bases de datos

Trampa de la partición default: la nueva partición falla con 'would be violated by some row'

PostgreSQLParticionamiento

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;

Qué hace

Cuenta por periodo las filas que han caído en la partición default; mueve las filas del rango de la nueva partición a una tabla nueva y la conecta, todo en una sola transacción.

Cuándo usarlo

Cuando CREATE TABLE ... PARTITION OF o ATTACH falla con 'updated partition constraint for default partition would be violated by some row', o cuando se detecta que la partición default está creciendo.

Precaución

Si hay una partición default, cada partición nueva la recorre por completo y mientras tanto mantiene ACCESS EXCLUSIVE sobre ella; una partición default grande significa una caída en cada mantenimiento. La default queda cerrada a escrituras mientras se mueven las filas; hágalo con poco tráfico. Solución permanente: cree las particiones de antemano y mantenga vacía la default con monitoreo (alerta si el número de filas > 0), o no la use, para que los INSERT fuera de rango fallen y el problema aflore pronto. Una partición default también impide DETACH ... CONCURRENTLY.

Abrir en DBAtlas →

Relacionado