Index corrompus dans PG12, comment les réparer ?

Désolé de remonter ce sujet une nouvelle fois, j’ai rencontré une erreur très étrange :

discourse=# REINDEX SCHEMA CONCURRENTLY public;
ERROR:  could not create unique index "index_tags_on_name_ccnew"
DETAIL:  Key (name)=(chronicillness) is duplicated.

Je suppose que cela peut être résolu grâce à la solution suggérée plus haut par @riking, mais je n’arrive pas à comprendre comment adapter la syntaxe à mon cas. :frowning:

Voir :

https://twitter.com/petervgeoghegan/status/1264325695997538304?s=20

https://twitter.com/petervgeoghegan/status/1264404749899534338?s=20

Ainsi, vous avez deux options si vous rencontrez cette erreur :

  1. Vous pouvez contourner le problème… dans ce cas, la table tags contient une ligne en double avec le nom chronicillness

    1. Effectuez une requête dans l’explorateur de données pour rechercher les lignes : select * from tags where name = 'chronicillness

    2. Supprimez le doublon :

      ./launcher enter app
      rails c
      Tag.find_by(id: ID_TROUVÉ_DANS_L_EXPLORATEUR_DE_DONNÉES).destroy   
      
  2. Si vous disposez d’une sauvegarde de votre base de données et de détails que vous souhaitez partager avec Peter… partagez-les avec Peter, soit en privé, soit sur la liste de diffusion PG.

J’ai donc une sauvegarde générée par Discourse de PostgreSQL 10. Cela sera-t-il utile ? Puis-je simplement extraire la partie PostgreSQL de l’archive et l’envoyer ?

Je ne suis pas sûr… Ce dont Peter a probablement besoin, c’est que vous arrêtiez votre base de données et que vous copiiez l’intégralité du contenu du dossier contenant la base de données.

Le meilleur moyen de le savoir est de lui envoyer un e-mail.

Bien sûr, je vais lui envoyer un e-mail pour régler cela :slight_smile:

NB : Voici ce que j’ai obtenu en exécutant la requête SQL dans l’explorateur de données

id name topic_count created_at updated_at pm_topic_count target_tag
1710 chronicillness 2 2019-12-03T17:49:17.395Z 2019-12-03T17:49:17.395Z 0 NULL

Est-ce que

Tag.find_by(id: 1710).destroy

va fonctionner ?

oh … l’index est sur LOWER(name)

Exécutez la requête comme suit :

select * from tags where name ilike 'chronicillness'

Vous devriez obtenir 2 lignes.

select * from tags where name ilike 'chronicillness'
id name topic_count created_at updated_at pm_topic_count target_tag
329 chronicillness 12 2017-08-22T00:17:38.824Z 2017-08-22T00:17:38.824Z 0 NULL
1710 chronicillness 2 2019-12-03T17:49:17.395Z 2019-12-03T17:49:17.395Z 0 NULL

Est-ce qu’il pourrait y avoir un - entre les noms des tags ?
Je vois deux tags : chronicillness et chronic-illness ici.

Eh bien, c’est donc le problème… Je suppose que vous supprimez 1710. Deux sujets manqueront alors de ce tag.

#<Tag:0x00005607bb92cf48
 id: 1710,
 name: "chronicillness",
 topic_count: 0,
 created_at: mar. 03 déc. 2019 17:49:17 UTC +00:00,
 updated_at: mar. 03 déc. 2019 17:49:17 UTC +00:00,
 pm_topic_count: 0,
 target_tag_id: nil>

Pourquoi ai-je l’impression que c’était un nain qui n’était associé à rien ?

La suppression de l’étiquette a généré davantage de problèmes !

discourse=# REINDEX SCHEMA CONCURRENTLY public;
AVERTISSEMENT : impossible de réindexer concurremment l'index invalide "public.tags_pkey_ccnew", ignoré
AVERTISSEMENT : impossible de réindexer concurremment l'index invalide "public.index_tags_on_name_ccnew", ignoré
AVERTISSEMENT : impossible de réindexer concurremment l'index invalide "public.index_tags_on_lower_name_ccnew", ignoré
AVERTISSEMENT : impossible de réindexer concurremment l'index invalide "pg_toast.pg_toast_309322_index_ccnew", ignoré
ERREUR : échec de la création de l'index unique "index_tags_on_name_ccnew1"
DÉTAIL : La clé (name)=(time-management) est dupliquée.

Même correction :slight_smile: Il faut répéter le processus.

C’est ce que je faisais. Mais ces avertissements sont-ils acceptables ? Je n’ai pas à m’en soucier, n’est-ce pas ?

Oui, tous les avertissements sont corrects : votre index est corrompu et doit être réparé en premier.

Donc, tous les copies sont maintenant partis et je ne suis laissé qu’avec ces avertissements lors de la réindexation :

discourse=# REINDEX SCHEMA CONCURRENTLY public;
AVERTISSEMENT : impossible de réindexer simultanément l'index invalide "public.tags_pkey_ccnew", saut
AVERTISSEMENT : impossible de réindexer simultanément l'index invalide "public.index_tags_on_name_ccnew", saut
AVERTISSEMENT : impossible de réindexer simultanément l'index invalide "public.index_tags_on_lower_name_ccnew", saut
AVERTISSEMENT : impossible de réindexer simultanément l'index invalide "public.tags_pkey_ccnew1", saut
AVERTISSEMENT : impossible de réindexer simultanément l'index invalide "public.index_tags_on_name_ccnew1", saut
AVERTISSEMENT : impossible de réindexer simultanément l'index invalide "public.index_tags_on_lower_name_ccnew1", saut
AVERTISSEMENT : impossible de réindexer simultanément l'index invalide "pg_toast.pg_toast_309322_index_ccnew", saut
AVERTISSEMENT : impossible de réindexer simultanément l'index invalide "pg_toast.pg_toast_309322_index_ccnew1", saut
REINDEX

Y a-t-il quelque chose à faire pour se débarrasser de ces avertissements ou devons-nous vivre avec ?

C’est confus pour moi… nous n’avons aucun nom d’index se terminant par ccnew… les avez-vous créés manuellement ?

Je pense qu’ils sont utilisés lors de la migration de PostgreSQL 10 vers 12, car je les ai vus chez presque tous les utilisateurs dont les index ont rencontré des problèmes. Par exemple :
https://meta.discourse.org/t/postgresql-12-update/151236/208?u=itsbhanusharma

https://meta.discourse.org/t/postgresql-12-update/151236/237?u=itsbhanusharma

MODIF : provient de PostgreSQL lui-même

La méthode de récupération recommandée dans de tels cas consiste à supprimer l’index invalide et à réessayer d’exécuter REINDEX CONCURRENTLY. L’index concurrent créé pendant le traitement porte un nom se terminant par le suffixe ccnew, ou ccold s’il s’agit d’une ancienne définition d’index que nous n’avons pas réussi à supprimer. Les index invalides peuvent être supprimés à l’aide de DROP INDEX, y compris les index toast invalides.

Ouch … les bons index sont-ils déjà présents dans la table ?

Je pense que vous pouvez lister les index de la table en utilisant l’explorateur de données.

Si les bons sont là, vous pouvez simplement supprimer ces index problématiques.

Laissez-moi vérifier. Je vous tiens au courant.

Donc, les index semblent exister

Des index dupliqués existent également pour les index problématiques, avec l’ajout de ccnew ou ccnew1.

Je ne connais pas de méthode pour vérifier si ces index sont valides, mais si les supprimer est une option, je serai ravi de les supprimer et de les reconstruire.

EDIT : la commande DROP INDEX fonctionnera-t-elle comme suggéré ici ?

Ouais, supprimez-les tous… je ne sais pas comment ils sont arrivés là… DROP INDEX est ce que vous voulez utiliser.

./launcher enter app
rails c
DB.exec('drop index tags_pkey_ccnew1')