Quelle est la meilleure façon d'automatiser la sauvegarde des bases de données PostgreSQL?


22

Je trouve fastidieux d'avoir à sauvegarder des bases de données chaque semaine. Et je pense aussi que les sauvegardes hebdomadaires devraient être transformées en sauvegardes quotidiennes. Si je devais le faire, je ne veux pas le faire manuellement. Quelle est la meilleure façon d'automatiser quotidiennement la sauvegarde des bases de données PostgreSQL?


Petite remarque: le vidage de la base de données peut tuer les performances, utiliser un cluster et effectuer un vidage sur les nœuds non actifs.
neutrinus

Vous pouvez effectuer des sauvegardes planifiées à l'aide de cet outil gratuit postgresql-backup.com
Olek Nilson

Question suivante: Quelle est votre taille, quel mécanisme de sauvegarde général avez-vous mis en place? Par exemple, je ne sauvegarde jamais rien manuellement. Installer l'agent de mon système de sauvegarde, sélectionner les éléments à sauvegarder dans l'interface utilisateur, planifier la sauvegarde (dans mon cas pour les bases de données: toutes les 5 minutes) .... terminé. Mais cela suppose d'en avoir suffisamment pour installer un système approprié.
TomTom

Je n'appellerais pas postgresql-backup.com une solution "gratuite". Il n'est gratuit que pour les 2 premières bases de données ... @OlekNilson
Aidan Melen

Réponses:


40

de la même manière que pour toute autre tâche répétitive pouvant être automatisée - vous écrivez un script pour effectuer la sauvegarde, puis configurez un travail cron pour l'exécuter.

un script comme le suivant, par exemple:

(Remarque: il doit être exécuté en tant qu'utilisateur postgres, ou tout autre utilisateur avec les mêmes privilèges)

#! /bin/bash

# backup-postgresql.sh
# by Craig Sanders <cas@taz.net.au>
# This script is public domain.  feel free to use or modify
# as you like.

DUMPALL='/usr/bin/pg_dumpall'
PGDUMP='/usr/bin/pg_dump'
PSQL='/usr/bin/psql'

# directory to save backups in, must be rwx by postgres user
BASE_DIR='/var/backups/postgres'
YMD=$(date "+%Y-%m-%d")
DIR="$BASE_DIR/$YMD"
mkdir -p "$DIR"
cd "$DIR"

# get list of databases in system , exclude the tempate dbs
DBS=( $($PSQL --list --tuples-only |
          awk '!/template[01]/ && $1 != "|" {print $1}') )

# first dump entire postgres database, including pg_shadow etc.
$DUMPALL --column-inserts | gzip -9 > "$DIR/db.out.gz"

# next dump globals (roles and tablespaces) only
$DUMPALL --globals-only | gzip -9 > "$DIR/globals.gz"

# now loop through each individual database and backup the
# schema and data separately
for database in "${DBS[@]}" ; do
    SCHEMA="$DIR/$database.schema.gz"
    DATA="$DIR/$database.data.gz"
    INSERTS="$DIR/$database.inserts.gz"

    # export data from postgres databases to plain text:

    # dump schema
    $PGDUMP --create --clean --schema-only "$database" |
        gzip -9 > "$SCHEMA"

    # dump data
    $PGDUMP --disable-triggers --data-only "$database" |
        gzip -9 > "$DATA"

    # dump data as column inserts for a last resort backup
    $PGDUMP --disable-triggers --data-only --column-inserts \
        "$database" | gzip -9 > "$INSERTS"

done

# delete backup files older than 30 days
echo deleting old backup files:
find "$BASE_DIR/" -mindepth 1 -type d -mtime +30 -print0 |
    xargs -0r rm -rfv

EDIT:
pg_dumpall -D switch (ligne 27) est obsolète, maintenant remplacé par --column-inserts
https://wiki.postgresql.org/wiki/Deprecated_Features


10
+1 pour un excellent script
rkthkr

J'utilise quelque chose de très similaire comme PreDumpCmd pour backuppc, à l'exception que je n'encode pas la date dans le chemin, car backuppc traite de la conservation de plusieurs copies.
David Pashley

2
Excellent script, mais j'ai trouvé que je devais modifier le regex de telle sorte qu'il n'inclue pas de tuyaux et de lignes vides comme noms de base de données. DBS=$($PSQL -l -t | egrep -v 'template[01]' | awk '{print $1}' | egrep -v '^\|' | egrep -v '^$')
s29

@ s29 Je pense qu'il vaut mieux utiliser une requête directe au lieu de tout ce piratage grep, comme: DBS = ($ ($ {PSQL} -t -A -c "sélectionnez le nom de données dans pg_database où le nom de données n'est pas dans ('template0', ' template1 ') "))
PolyTekPatrick

Script génial - comment cela se compare-t-il à des services comme ClusterControl?
karns

7
pg_dump dbname | gzip > filename.gz

Recharger avec

createdb dbname
gunzip -c filename.gz | psql dbname

ou

cat filename.gz | gunzip | psql dbname

Utilisez split. La splitcommande vous permet de diviser la sortie en morceaux dont la taille est acceptable pour le système de fichiers sous-jacent. Par exemple, pour faire des morceaux de 1 mégaoctet:

pg_dump dbname | split -b 1m - filename

Recharger avec

createdb dbname
cat filename* | psql dbname

Vous pourriez jeter l'un de ceux /etc/cron.hourly

Provenant de http://www.postgresql.org/docs/8.1/interactive/backup.html#BACKUP-DUMP-ALL


Le fractionnement du fichier est une excellente idée. Il est préférable de diviser le vidage à l'aide de split -C, afin qu'une ligne ne soit jamais divisée. Le débogage d'une restauration ayant échoué est plus facile.
Gianluca Della Vedova

3

Quelles que soient les commandes que vous émettez "à la main", - écrivez-les dans le script et appelez ce script dans cron ou dans le planificateur que vous utilisez.

Vous pouvez bien sûr rendre le script plus sophistiqué, mais en général, je pense que vous y arriverez - commencez simplement et affinez plus tard.

Script le plus simple possible:

#!/bin/bash
/usr/local/pgsql/bin/pg_dumpall -U postgres -f /var/backups/backup.dump

Enregistrez-le sous /home/randell/bin/backup.sh, ajoutez-le à cron:

0 0 * * 0 /home/randell/bin/backup.sh

SI pg_dumpall est utilisé, est-il possible de restaurer une seule table à partir de celle-ci ou de restaurer tout à la fois? pouvez-vous s'il vous plaît partager le script pour restaurer une table unique créée en utilisant dumpall
Ashish Karpe

0

Si vous souhaitez sauvegarder un cluster entier avec une charge système minimale, vous pouvez simplement tarer le répertoire racine du cluster postgresql. par exemple:

echo "select pg_start_backup('full backup - `date`');" | psql
/usr/bin/rdiff-backup --force --remove-older-than 7D $BACKUP_TARGET
/usr/bin/rdiff-backup --include '/etc/postgresql' --include $PGDATA --exclude '/*' / $BACKUP_TARGET
/bin/tar -cjf /mnt/tmp/$SERVER_NAME.tbz2 $BACKUP_TARGET 2>&1
echo "select pg_stop_backup();" | psql

c'est l'essentiel de mon script de sauvegarde.


1
Non, cela ne fonctionne pas si l'archivage WAL n'est pas également activé.
Peter Eisentraut

0

au cas où quelqu'un devrait sauvegarder leurs postgres sur une machine Windows sans l'aide de cygwin, etc. J'ai un fichier batch qui fait très bien le travail.

cela sauvegardera les bases de données dans des fichiers individuels dans son propre répertoire tous les jours

set dtnm=%date:~-4,4%%date:~-7,2%%date:~0,2%
set bdir=D:\backup\%dtnm%
mkdir %bdir%

FOR /F "tokens=1,2 delims=|" %%a IN ('psql -l -t -A -U postgres') DO (
    IF %%b EQU postgres pg_dump -U postgres -f %bdir%\%%a.sql.gz -Z 9 -i %%a
)
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.