Cómo arreglé una tabla de postgres

Escribo esta publicación sobre un error de fragmento faltante en una tabla de postgres que estaba fallando mis copias de seguridad diarias. Logré solucionarlo y quiero exponer el método que utilicé en caso de que sea útil para alguien que encuentre este problema. De ninguna manera esta es una guía o instrucciones profesionales sobre cómo resolver correctamente los errores de fragmentos faltantes de postgres porque no soy un experto e hice esto sin tener mucho conocimiento, pero al final funcionó.

El error que estaba recibiendo durante las copias de seguridad:

pg_dump: error: Volcado del contenido de la tabla "stylesheet_cache" falló: PQgetResult() falló.
pg_dump: error: Mensaje de error del servidor: ERROR:  missing chunk number 0 for toast value 1903804 in pg_toast_22663
pg_dump: error: El comando fue: COPY public.stylesheet_cache (id, target, digest, content, created_at, updated_at, theme_id, source_map) TO stdout;

Entonces, el problema estaba en la tabla stylesheet_cache, ERROR: missing chunk number 0 for toast value 1903804 in pg_toast_22663.

Estoy usando Discourse en Docker, así que esto es lo que hice:

ssh al servidor
cd /ruta/a/discourse
./launcher rebuild app
su postgres -c "psql discourse"

Una vez que estuve en postgres, intenté REINDEXAR la tabla con la esperanza de que resolviera el problema.

discourse=# select reltoastrelid::regclass from pg_class where relname = 'stylesheet_cache';
      reltoastrelid      
------------------------─
 pg_toast.pg_toast_18396
(1 row)
REINDEX table stylesheet_cache;
REINDEX table pg_toast.pg_toast_18396;
VACUUM analyze stylesheet_cache;

Intenté hacer la copia de seguridad de nuevo, todavía falló, así que tuve que seguir buscando la corrupción.

Calculé el número total de filas en mi tabla con:

select count(*) from stylesheet_cache;

Obtuve un recuento de 2260 filas.

Fui a buscar la fila exacta que estaba corrupta y la eliminé, de alguna manera asumí que stylesheet_cache no es algo que realmente pueda romper toda mi base de datos. Como mencioné, no soy un experto, así que tal vez di un salto de fe demasiado grande, así que ten cuidado al hacer esto, ya que podrías dañar tu base de datos.

Usé las consultas LIMIT y OFFSET para encontrar las filas corruptas

select * from stylesheet_cache order by id limit 100 offset 0;

Jugué con el offset y el limit hasta que obtuve el error Missing chunk… y luego lo reduje a LIMIT 1 y el offset de la fila que estaba corrupta. En mi caso, había 5 filas corruptas.

Podrías usar un script sh para encontrar la fila con menos esfuerzo, yo fui por el camino manual que tomó algo de tiempo, pero podrías usar esto:

#!/bin/sh
j=0
while [ $j -lt 2260 ]
do
  psql -U postgres -d discourse -c "SELECT * FROM stylesheet_cache LIMIT 1 offset $j" >/dev/null || echo $j
  j=$(($j+1))
done

Fui a buscar el id de la fila corrupta con el siguiente comando:

select id from stylesheet_cache order by id limit 1 offset 450;

id

----

11498

Así que el id de mi fila corrupta era 11498
Eliminé la fila con

delete from stylesheet_cache where id = 11498;

Después de eliminar las filas corruptas, volví a REINDEXAR

REINDEX table stylesheet_cache;
REINDEX table pg_toast.pg_toast_40948;
VACUUM analyze stylesheet_cache;

Y volví a intentar la copia de seguridad, esta vez funcionó. Me guié utilizando estas instrucciones de recuperación de postgres: Postgres error: Missing chunk 0 for toast value in pg_toast · GitHub

DESCARGO DE RESPONSABILIDAD: esta no es una opinión de experto, así que proceda con precaución si tiene corrupciones de fragmentos faltantes similares y está intentando solucionarlas.

3 Me gusta