J'ai besoin d'exécuter VACUUM FULL sans espace disque disponible

27

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 j'ai pensé que c'était la meilleure option dans ce scénario.

Toute idée serait appréciée.

J'utilise PostgreSQL 9.0.6

Justin
la source

Réponses:

19

Puisque 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/

3 Arrêtez Postgresql

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

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

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

5 Exécutez initdb pour redynamiser 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
Craig Efrein
la source
1
Merci, c'est ce que j'ai fini par faire, avec quelques différences. Je viens de supprimer la base de données après l'avoir sauvegardée. Puis en a créé un nouveau et l'a restauré.
Justin
De rien. J'ai pensé que supprimer le contenu du répertoire de données et faire initdb aurait été suffisant.
Craig Efrein
Fonctionne très bien, je recommande simplement de sauter la gzippartie pour gagner du temps.
Rafael Barbosa
17

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.


ATTENTION (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 s'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éphanementionné dans les commentaires, celui-ci doit être au moins deux fois plus grand que le tableau en question comme le VACUUM FULLfait une copie complète. Si vous êtes chanceux et pouvez ajouter dynamiquement un disque à la machine, faites-le. Dans le pire des cas, 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 le cas NULL, ce sera dans le tablespace par défaut:

SHOW default_tablespace;

Si c'est aussi bien, il sera probablement (vérifier les documents officiels dans le cas où il a changé).NULLpg_default

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;
exhuma
la source
NB: le déplacement semble utiliser plus d'espace disque dans le répertoire de données d'origine ...
Chris Withers
Je viens de le tester sur 9.3 et cela fonctionne comme un charme.
Bartek Jablonski
Utilisé avec succès en production le 9.1. Après avoir changé l'espace disque logique, l'espace utilisé d'origine est libéré. Notez qu'une charge CPU élevée due aux opérations d'E / S peut être attendue.
erny
2
Des conseils incroyables, merci pour cette explication détaillée. Notez que sur l'espace table temporaire, vous aurez besoin d'au moins size of table x 2, car il VACUUM FULLs'agit de faire une copie complète de la table.
Stéphane
Merci @ Stéphane. J'ai ajouté les informations au corps principal.
exhuma
2

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

Roger Dahl
la source
0

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, maintenant il devrait lire les données de l'autre disque et écrire la table finale sur votre disque de données d'origine.
Gunther
la source