Wie kann die Sicherung von PostgreSQL-Datenbanken am besten automatisiert werden?

22

Ich finde es mühsam, jede Woche Datenbanken sichern zu müssen. Und ich denke auch, dass wöchentliche Backups in tägliche Backups umgewandelt werden sollten. Wenn ich das tun müsste, möchte ich es nicht manuell tun. Wie kann die tägliche Sicherung von PostgreSQL-Datenbanken am besten automatisiert werden?

Randell
quelle
Kleiner Hinweis: Das Speichern der Datenbank kann die Leistung beeinträchtigen, einen Cluster verwenden und auf nicht aktiven Knoten speichern.
Neutrinus
Sie können geplante Backups mit Hilfe dieses kostenlosen Tools erstellen. Postgresql-backup.com
Olek Nilson
Nächste Frage: Wie groß sind Sie, über welchen allgemeinen Sicherungsmechanismus verfügen Sie? Zum Beispiel mache ich nie ein manuelles Backup. Installieren Sie den Agenten meines Backup-Systems, wählen Sie die Elemente aus, die in der Benutzeroberfläche gesichert werden sollen, und planen Sie das Backup (in meinem Fall für Datenbanken: alle 5 Minuten). Dies setzt jedoch voraus, dass es sinnvoll ist, ein ordnungsgemäßes System zu installieren.
TomTom
Ich würde postgresql-backup.com nicht als "kostenlose" Lösung bezeichnen. Es ist nur für die ersten 2 Datenbanken kostenlos ... @OlekNilson
Aidan Melen

Antworten:

40

So wie bei jeder anderen sich wiederholenden Aufgabe, die automatisiert werden kann: Sie schreiben ein Skript, um die Sicherung durchzuführen, und richten dann einen Cron-Job ein, um ihn auszuführen.

ein Skript wie das folgende zum Beispiel:

(Hinweis: Es muss als postgres-Benutzer oder jeder andere Benutzer mit denselben Berechtigungen ausgeführt werden.)

#! /bin/bash

# backup-postgresql.sh
# by Craig Sanders <[email protected]>
# 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

BEARBEITEN:
pg_dumpall -D Schalter (Zeile 27) ist veraltet und wird jetzt durch --column-inserts
https://wiki.postgresql.org/wiki/Deprecated_Features ersetzt

cas
quelle
10
+1 für ein tolles Drehbuch
rkthkr
Ich verwende etwas sehr Ähnliches wie PreDumpCmd für die Sicherung, mit der Ausnahme, dass ich das Datum nicht in den Pfad einkodiere, da die Sicherung die Aufbewahrung mehrerer Kopien übernimmt.
David Pashley
2
Tolles Skript, aber ich musste den regulären Ausdruck so anpassen, dass keine Pipes und Leerzeilen als Datenbanknamen enthalten waren. DBS=$($PSQL -l -t | egrep -v 'template[01]' | awk '{print $1}' | egrep -v '^\|' | egrep -v '^$')
S29
@ s29 Ich denke, es ist besser, eine direkte Abfrage anstelle von all dem Grep-Hackery zu verwenden, wie: DBS = ($ ($ {PSQL} -t -A -c "Datenname aus pg_database auswählen, wobei Datenname nicht in ('template0', ' template1 ') "))
PolyTekPatrick
Tolles Skript - wie ist das im Vergleich zu Diensten wie ClusterControl?
Karns
7
pg_dump dbname | gzip > filename.gz

Nachladen mit

createdb dbname
gunzip -c filename.gz | psql dbname

oder

cat filename.gz | gunzip | psql dbname

Verwenden Sie split. Mit dem splitBefehl können Sie die Ausgabe in Teile aufteilen, deren Größe für das zugrunde liegende Dateisystem akzeptabel ist. Zum Beispiel, um Stücke von 1 Megabyte zu machen:

pg_dump dbname | split -b 1m - filename

Nachladen mit

createdb dbname
cat filename* | psql dbname

Du könntest einen von denen reinwerfen /etc/cron.hourly

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

Nick Anderson
quelle
Das Aufteilen der Datei ist eine großartige Idee. Es ist besser, den Speicherauszug mit zu teilen split -C, damit eine Zeile niemals geteilt wird. Das Debuggen einer fehlgeschlagenen Wiederherstellung ist einfacher.
Gianluca Della Vedova
3

Welche Befehle Sie auch "von Hand" ausgeben, - schreiben Sie sie in das Skript und rufen Sie dieses Skript in cron oder einem anderen von Ihnen verwendeten Scheduler auf.

Sie können das Skript natürlich ausgefallener gestalten, aber im Allgemeinen denke ich, dass Sie es schaffen werden - beginnen Sie einfach und verfeinern Sie es später.

Einfachstes mögliches Skript:

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

Speichern Sie es unter /home/randell/bin/backup.sh und fügen Sie es zu cron hinzu:

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

quelle
WENN pg_dumpall verwendet wird, ist es möglich, eine einzelne Tabelle daraus wiederherzustellen, oder wird alles auf einmal wiederhergestellt? Können Sie bitte das Skript für die Wiederherstellung einer einzelnen Tabelle teilen, die mit dumpall
Ashish Karpe
0

Wenn Sie einen gesamten Cluster mit minimaler Systemlast sichern möchten, können Sie einfach das Stammverzeichnis des postgresql-Clusters tarieren. beispielsweise:

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

Das ist der Großteil meines Backup-Skripts.

Lee
quelle
1
Nein, dies funktioniert nicht, wenn Sie die WAL-Archivierung nicht aktiviert haben.
Peter Eisentraut
0

Für den Fall, dass jemand seine Postgres auf einem Windows-Rechner ohne die Hilfe von Cygwin usw. sichern muss, habe ich eine Batch-Datei, die den Job ziemlich gut macht.

Dadurch werden die Datenbanken jeden Tag in einzelne Dateien in einem eigenen Verzeichnis gesichert

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
)
l0ft13
quelle