web-dev-qa-db-fra.com

Je dois exécuter VACUUM FULL sans espace disque disponible

J'ai une table qui occupe près de 90% de l'espace HD sur notre serveur. J'ai décidé de supprimer quelques colonnes pour libérer de l'espace. Mais je dois restituer l'espace au système d'exploitation. Le problème, cependant, est que je ne sais pas ce qui se passera si j'exécute VACUUM FULL et qu'il n'y a pas assez d'espace libre pour faire une copie de la table.

Je comprends que VACUUM FULL ne doit pas être utilisé mais je me suis dit que c'était la meilleure option dans ce scénario.

Toute idée serait appréciée.

J'utilise PostgreSQL 9.0.6

31
Justin

Comme vous n'avez pas assez d'espace pour exécuter un vacumm ou reconstruire, vous pouvez toujours reconstruire vos bases de données postgresql en les restaurant. La restauration des bases de données, des tables et des index permettra de libérer de l'espace et de la défragmentation. Ensuite, vous pouvez configurer une maintenance automatisée pour vacumm vos bases de données sur une base régulière.

1 Sauvegardez toutes les bases de données sur votre serveur postgresql

Vous souhaiterez sauvegarder toutes vos bases de données sur une partition qui a suffisamment d'espace. Si vous étiez sous Linux, vous pouvez utiliser gzip pour compresser davantage la sauvegarde pour économiser de l'espace

su - postgres
pg_dumpall | gzip -9 > /some/partition/all.dbs.out.gz

2 Sauvegardez vos fichiers de configuration

cp /path/to/postgresql/data_directory/*.conf /some/partition/

Stop Postgresql

pg_ctl -D /path/to/postgresql/data_directory stop

4 efface le contenu du répertoire de données

rm -Rf /path/to/postgresql/data_directory/*

5 Exécutez initdb pour réinitialiser votre répertoire de données

initdb -D /path/to/postgresql/data_directory

6 Restaurer les fichiers de configuration

cp /some/partition/*.conf /path/to/postgresql/data_directory/*.conf 

7 Démarrer Postgresql

pg_ctl -D /path/to/postgresql/data_directory start

8 Restaurez le vidage de toutes les bases de données que vous avez créées

gunzip /some/partition/all.dbs.out.gz
psql -f /some/partition/all.dbs.out
20
Craig Efrein

REMARQUE: j'ai testé cela sur 9.1. Je n'ai pas de serveur 9.0 qui traîne ici. Je suis sûr que cela fonctionnera bien sur 9.0.


[~ # ~] prudence [~ # ~] (Comme indiqué dans les commentaires de @erny):

Note that high CPU load due to I/O operations may be expected.

Vous pouvez le faire sans pratiquement aucun temps d'arrêt en utilisant un espace de table temporaire. Le temps d'arrêt sera sous la forme de verrous exclusifs. Mais seulement sur la table, vous passez l'aspirateur. Donc, tout ce qui se passera, c'est que les requêtes des clients attendront simplement que le verrou soit acquis si ils accèdent à la table en question. Vous n'avez pas besoin de fermer les connexions existantes.

Une chose à savoir cependant, c'est que le déplacement de la table et le vide complet devront eux-mêmes attendre d'abord un verrou exclusif!


Tout d'abord, vous avez évidemment besoin de stockage supplémentaire. Comme Stéphane mentionne dans les commentaires, cela doit être au moins deux fois plus grand que le tableau en question que VACUUM FULL fait une copie complète. Si vous êtes chanceux et pouvez ajouter dynamiquement un disque à la machine, faites-le. Dans le cas pire vous pouvez simplement connecter un disque USB (risqué et lent cependant)!

Ensuite, montez le nouveau périphérique et rendez-le disponible en tant qu'espace disque logique:

CREATE TABLESPACE tempspace LOCATION '/path/to/new/folder';

Vous pouvez facilement répertorier les espaces disque logiques en utilisant:

\db

Revérifiez l'espace de table actuel de votre table (vous devez savoir où le déplacer):

SELECT tablespace FROM pg_tables WHERE tablename = 'mytable';

Si c'est NULL, ce sera dans le tablespace par défaut:

SHOW default_tablespace;

Si ça est également NULL, ce sera probablement pg_default (vérifiez les documents officiels au cas où cela changerait).

Déplacez maintenant le tableau:

ALTER TABLE mytable SET TABLESPACE tempspace;
COMMIT;  -- if autocommit is off

Passez l'aspirateur:

VACUUM FULL mytable;

Reculez:

-- assuming you are using the defaults, the tablespace will be "pg_default".
-- Otherwise use the value from the SELECT we did earlier.
ALTER TABLE mytable SET TABLESPACE pg_default;
COMMIT;  -- if autocommit is off

Supprimez l'espace temporaire:

DROP TABLESPACE tempspace;
18
exhuma

Rapide et sale:

  • Arrêtez Postgres
  • Déplacez le répertoire de la base de données principale vers un autre disque où il y a suffisamment de place pour passer l'aspirateur
  • À l'emplacement d'origine de main, ajoutez un lien symbolique vers le nouvel emplacement
  • Vide
  • Supprimez le lien symbolique et ramenez le répertoire principal à son emplacement d'origine
  • Démarrer Postgres

Par exemple.,:

$ service postgresql stop $ mv /var/lib/postgresql/9.5/main /mnt/bigdisk $ ln -sr /mnt/bigdisk/main /var/lib/postgresql/9.5 $ vacuumdb --all --full $ rm /var/lib/postgresql/9.5/main $ mv /mnt/bigdisk/main /var/lib/postgresql/9.5 $ service postgresql start

3
Roger Dahl

Si vous disposez de l'espace disque pour effectuer un vidage et une restauration, vous devez disposer de l'espace disque pour effectuer un vacuumdb --full. Le problème est que vacuumdb --full fera une copie de tout le fichier de données. Donc, ce que vous pourriez faire, c'est:

  1. copiez les fichiers qui contiennent l'énorme table sur un autre lecteur, par exemple un lecteur plus lent et plus gros.
  2. créer des liens symboliques entre l'emplacement d'origine et le nouvel emplacement sur l'autre lecteur.
  3. exécutez vacuumdb --full, il devrait maintenant lire les données de l'autre disque et écrire la table finale sur votre disque de données d'origine.
0
Gunther