# n8n — index unique dégradé sur `insights_metadata` (collation Postgres) **Date** : 2026-07-23 · **Tags** : n8n, postgres, collation, index, insights · **Statut** : clos — laissé en l'état (décision assumée) ## Contexte Stack n8n NAS (Portainer stack **254**, DB `n8n-DB` / postgres 17-alpine, bind-mount `/volume1/docker/n8n/db`). Après la MAJ n8n 2.23.0 → 2.31.5, les tables `insights_*` (analytique interne n8n) présentaient des chiffres surestimés. ## Symptôme Toute session psql sur la base affiche : ``` WARNING: database "n8n" has no actual collation version, but a version was recorded ``` Conséquence : l'index **unique** `IDX_1d8ab99d5861c9388d2dc1cf73` sur `insights_metadata(workflowId)` est **dégradé** — il a laissé entrer des doublons. État constaté : **8 doublons de metadata**, **~13 workflows légèrement surcomptés** dans les insights. 69 lignes dans `insights_metadata`. Cause : la version de collation enregistrée dans le catalogue ne correspond plus à celle de la libc du conteneur (bascule d'image / de libc). Les index B-tree sur colonnes texte construits sous l'ancienne collation deviennent incohérents → l'unicité n'est plus garantie. ## Ce qui NE MARCHE PAS ### ❌ Restore littéral du dump `insights_*` Le réflexe « TRUNCATE + COPY depuis le backup » **échoue** : ``` BEGIN TRUNCATE TABLE ERROR: duplicate key value violates unique constraint "IDX_1d8ab99d5861c9388d2dc1cf73" DETAIL: Key ("workflowId")=(XNppr5IcEMfJ73Ep) already exists. CONTEXT: COPY insights_metadata, line 31 ``` **Pourquoi** : le `TRUNCATE` vide l'index, qui se **reconstruit au fil du COPY sous la collation courante** → il redevient strict. Or le backup contient les doublons d'origine (entrés à l'époque où l'index était dégradé). Le restore se mord la queue. ✅ **Le garde-fou a fonctionné** : `psql -v ON_ERROR_STOP=1` + `BEGIN` explicite → rollback complet, table inchangée (69 lignes avant/après). **Toujours encadrer un restore partiel par ON_ERROR_STOP + transaction.** ### ❌ Comptages naïfs Avec un index dégradé, les `SELECT count(*)` peuvent passer par l'index et renvoyer des chiffres incohérents. Forcer le parcours séquentiel pour un état fiable : ```sql SET enable_indexscan = off; SET enable_bitmapscan = off; SELECT count(*) FROM insights_metadata; ``` ## Ce qui marche ### Option A — restore dédupliqué (non retenue) Dédupliquer les données **hors ligne** (sur le dump, données statiques → fiable, insensible à l'index dégradé), puis `TRUNCATE` + `COPY` du fichier propre. L'index unique reconstruit l'accepte. Atomique, faible risque, mais perd le churn depuis le dump. ### Option B — ne rien faire (RETENUE le 23/07/2026) Les insights sont de l'**analytique bas-enjeu**, et n8n **churne la table en continu** : observé en direct, `insights_raw` 49 → 0 et `insights_by_period` 19347 → 19363 pendant la session (compaction en tâche de fond). Le surcomptage s'atténue seul avec la rétention. → Aucune chirurgie. Aucune perte de données, aucun impact fonctionnel sur les workflows. ## ⚠️ Bombe à retardement (à connaître avant tout geste futur) Tant que les doublons sont présents, **échoueront** : - `REINDEX` (index ou base) - `ALTER DATABASE n8n REFRESH COLLATION VERSION` - `pg_upgrade` - tout dump/restore **complet** de la base Si l'un de ces gestes devient nécessaire (montée de version postgres, changement d'image), **dédupliquer `insights_metadata` AVANT** : ```sql -- inspection préalable SELECT "workflowId", count(*) FROM insights_metadata GROUP BY 1 HAVING count(*) > 1; ``` ## Prévention - **Pin le patch postgres exact** dans le compose du stack (ex. `postgres:17.10-alpine`), jamais `postgres:17` flottant — c'est une bascule mineure/libc implicite qui produit ce type de désynchro de collation. Cf. `RUNBOOK-HERMES-UPDATE.md` et le piège 2 du stack n8n. - Après toute bascule d'image postgres, guetter le `WARNING ... collation version` en tête de session psql. ## Accès rapide ```bash ssh nas 'export PATH=$PATH:/usr/local/bin; docker exec -i n8n-DB psql -U n8nuser -d n8n' <<'SQL' 2>&1 | grep -vi "collation version" SELECT count(*) FROM insights_metadata; SQL ``` Voir aussi : `common/n8n-credentials-corruption-veille-consolidation.md`, `common/ports-registry.md`.