Error al importar copia de seguridad: "no se pudo crear el índice único"

Hola,

Estoy intentando migrar un foro a un nuevo servidor. Ambos servidores ejecutan la última versión de discourse docker. Al importar la copia de seguridad a través de la línea de comandos, obtengo el siguiente error:

ERROR:  no se pudo crear el índice único «index_incoming_referers_on_path_and_incoming_domain_id»
DETAIL:  La clave (path, incoming_domain_id)=(«/search/», 418) está duplicada.
EXCEPTION: psql falló: DETAIL:  La clave (path, incoming_domain_id)=(«/search/», 418) está duplicada.

Esto parece ser el mismo error o uno similar a:

Sin embargo, en mi caso, los registros duplicados están en la ruta /search/ en lugar de /m/search, como ocurre en el hilo enlazado anteriormente.

Me he conectado al contenedor en el servidor antiguo (./launcher enter app) y en la consola de Rails (rails c) he intentado buscar los registros duplicados usando:

IncomingReferer.where(path: "/search")
y
IncomingReferer.where("path LIKE '%/search%'")

Sin embargo, esto resulta en que se muestren cientos de registros. ¿Cómo puedo averiguar qué registros están duplicados y cómo puedo eliminarlos de forma segura y reconstruirlos? El foro está funcionando correctamente en el servidor antiguo, solo necesitamos movernos a hardware nuevo.

1 me gusta

¿Has intentado usar la interfaz gráfica de administración (Admin GUI)?

1 me gusta

No, asumí que importar mediante la GUI invocaría el mismo proceso de importación. Lo probaré ahora.

1 me gusta

Sospecho que esto significa que tienes un índice corrupto. ¿Qué versión de Postgres estás ejecutando?

Algo como:

cd /var/discourse
cat shared/standalone/postgres_data/PG*

(No recuerdo exactamente el nombre del archivo de Postgres).

Puedes buscar aquí “postgres corrupt index” y encontrar un tema que escribí una vez sobre cómo rastrear esos registros erróneos y eliminarlos.

Básicamente, intentas reconstruir ese índice y eliminar los registros de los que se queja, luego intentas reconstruir el índice nuevamente hasta que se reconstruya.

Acabo de intentar importar a través de la interfaz gráfica, con exactamente el mismo resultado:

El servidor antiguo no tiene un archivo llamado PG_VERSION, ¿cómo puedo saber qué versión está ejecutando? He actualizado la instalación de Docker a la versión más reciente hoy.

El nuevo servidor (recién inicializado) está ejecutando Postgres V13

cat shared/standalone/postgres_data/PG_VERSION
13

¿Existe un procedimiento recomendado para hacer esto?

Tuve un tema que tenía algunas pistas, pero ya no lo veo. Ha pasado casi un año desde la actualización a PostgreSQL 12.

  reindex index index_incoming_referers_on_path_and_incoming_domain_id;

Y

 ActiveRecord::Base.connection.execute('reindex index index_incoming_referers_on_path_and_incoming_domain_id;')

Son formas de intentar reconstruir el índice. Te dará un error y luego podrás ir y eliminar los registros erróneos. Necesitarás incluir tanto la ruta como el ID.

Ok, lo he solucionado. He realizado lo siguiente:

Entrar al contenedor

./launcher enter app

Conectarse a la base de datos

su postgres -c 'psql discourse'

Intentar encontrar duplicados

discourse=# select * from incoming_referers where path LIKE '%/search/' ORDER BY incoming_domain_id;

  id  |    path    | incoming_domain_id
------+------------+--------------------
 3339 | /search/   |                 33
 6257 | /search/   |                 91
 1567 | /search/   |                298
 1777 | /search/   |                341
 3010 | /search/   |                418
 6247 | /search/   |                418
 4293 | /search/   |                644
 2899 | /search/   |                653
 3447 | /search/   |                793
 3696 | /search/   |                852
 4395 | /a/search/ |               1050
 6968 | /search/   |               1305
 5634 | /search/   |               1387
 5834 | /search/   |               1437
 6519 | /search/   |               1637
 7127 | /search/   |               1787
 7280 | /search/   |               1827
(17 filas)

Eliminar duplicado

DELETE FROM incoming_referers WHERE path LIKE '%/search/' AND id IN (6247);

Luego reconstruir

discourse=# REINDEX SCHEMA CONCURRENTLY public;
WARNING:  cannot reindex invalid index "public.incoming_referers_pkey_ccnew" concurrently, skipping
WARNING:  cannot reindex invalid index "public.index_incoming_referers_on_path_and_incoming_domain_id_ccnew" concurrently, skipping
WARNING:  cannot reindex invalid index "pg_toast.pg_toast_20732_index_ccnew" concurrently, skipping
REINDEX

Después tomé otra copia de seguridad, la copié al nuevo servidor y se importó correctamente :smiley:

Sería ideal que el proceso de copia de seguridad pudiera detectar duplicados para evitar cualquier problema; tuve la suerte de tener acceso al servidor original que aún estaba en funcionamiento. Si hubiera estado restaurando una copia de seguridad inactiva, esto probablemente habría sido un problema mayor.

Muchas gracias por tu ayuda.

3 Me gusta

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.