Jaki jest najlepszy sposób na automatyzację tworzenia kopii zapasowych baz danych PostgreSQL?

22

Uważam, że tworzenie kopii zapasowych baz danych co tydzień jest uciążliwe. Myślę też, że cotygodniowe kopie zapasowe powinny zostać przekształcone w codzienne kopie zapasowe. Gdybym musiał to zrobić, nie chcę tego robić ręcznie. Jaki jest najlepszy sposób automatyzacji codziennego tworzenia kopii zapasowych baz danych PostgreSQL?

Randell
źródło
Mała uwaga: zrzut bazy danych może zabić wydajność, użyć klastra i zrzucić na nieaktywnych węzłach.
neutrinus
Możesz tworzyć zaplanowane kopie zapasowe za pomocą tego darmowego narzędzia postgresql-backup.com
Olek Nilson
Następne pytanie: jak duży jesteś, jaki masz ogólny mechanizm tworzenia kopii zapasowych. Na przykład nigdy nie tworzę kopii zapasowej niczego ręcznie. Zainstaluj agenta mojego systemu tworzenia kopii zapasowych, wybierz elementy do utworzenia kopii zapasowej w interfejsie użytkownika, zaplanuj tworzenie kopii zapasowej (w moim przypadku dla baz danych: co 5 minut) .... zakończone. Ale to zakłada wystarczającą ilość, aby sensownie zainstalować odpowiedni system.
TomTom
Nie nazwałbym postgresql-backup.com „darmowym” rozwiązaniem. Jest bezpłatny tylko dla pierwszych 2 baz danych ... @OlekNilson
Aidan Melen

Odpowiedzi:

40

tak samo jak w przypadku każdego innego powtarzalnego zadania, które można zautomatyzować - piszesz skrypt do wykonania kopii zapasowej, a następnie konfigurujesz zadanie crona, aby je uruchomić.

skrypt taki jak na przykład:

(Uwaga: musi być uruchamiany jako użytkownik postgres lub jakikolwiek inny użytkownik z tymi samymi uprawnieniami)

#! /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

EDYCJA:
pg_dumpall -D przełącznik (wiersz 27) jest przestarzały, teraz zastąpiony przez --column-inserts
https://wiki.postgresql.org/wiki/Deprecated_Features

cas
źródło
10
+1 za świetny skrypt
rkthkr
Używam czegoś bardzo podobnego jako PreDumpCmd dla backuppc, z tym wyjątkiem, że nie koduję daty w ścieżce, ponieważ backuppc zajmuje się przechowywaniem wielu kopii.
David Pashley,
2
Świetny skrypt, ale stwierdziłam, że muszę tak dostosować regex, aby nie zawierał potoków i pustych linii jako nazw baz danych. DBS=$($PSQL -l -t | egrep -v 'template[01]' | awk '{print $1}' | egrep -v '^\|' | egrep -v '^$')
s29
@ s29 Myślę, że lepiej jest użyć bezpośredniego zapytania zamiast całego tego hakowania grep, takiego jak: DBS = ($ ($ {PSQL} -t -A -c "wybierz nazwę bazy danych z pg_database gdzie nazwa nie jest zawarta ('template0', ' template1 ') "))
PolyTekPatrick
Niesamowity skrypt - jak to porównać z usługami takimi jak ClusterControl?
karns
7
pg_dump dbname | gzip > filename.gz

Załaduj ponownie za pomocą

createdb dbname
gunzip -c filename.gz | psql dbname

lub

cat filename.gz | gunzip | psql dbname

Zastosowanie split. splitKomenda pozwala podzielić wyjście na kawałki, które są dopuszczalne w rozmiarze do bazowego systemu plików. Na przykład, aby utworzyć fragmenty o wielkości 1 megabajta:

pg_dump dbname | split -b 1m - filename

Załaduj ponownie za pomocą

createdb dbname
cat filename* | psql dbname

Możesz wrzucić jednego z nich /etc/cron.hourly

Źródło: http://www.postgresql.org/docs/8.1/interactive/backup.html#BACKUP-DUMP-ALL

Nick Anderson
źródło
Podział pliku to świetny pomysł. Lepiej jest podzielić zrzut, używając split -C, aby linia nigdy nie była dzielona. Debugowanie nieudanego przywracania jest łatwiejsze.
Gianluca Della Vedova
3

Bez względu na to, jakie polecenia wydajesz „ręcznie”, - zapisz je w skrypcie i wywołaj ten skrypt w cronie lub dowolnym używanym harmonogramie.

Możesz oczywiście uczynić skrypt bardziej fantazyjnym, ale ogólnie myślę, że tam dotrzesz - zacznij od prostych, a później dopracuj.

Najprostszy możliwy skrypt:

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

Zapisz go jako /home/randell/bin/backup.sh, dodaj do crona:

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

źródło
JEŚLI używana jest pg_dumpall, czy można przywrócić z niej pojedynczą tabelę, czy przywróci ona wszystkie naraz? czy możesz udostępnić skrypt do przywrócenia pojedynczej tabeli utworzonej za pomocą dumpall
Ashish Karpe
0

Jeśli chcesz wykonać kopię zapasową całego klastra przy minimalnym obciążeniu systemu, możesz po prostu spakować katalog główny klastra postgresql. na przykład:

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

to większość mojego skryptu zapasowego.

zawietrzny
źródło
1
Nie, to nie działa, jeśli nie masz włączonej archiwizacji WAL.
Peter Eisentraut
0

na wypadek, gdyby ktoś musiał wykonać kopię zapasową swoich postgresów na komputerze z systemem Windows bez pomocy cygwina itp. Mam plik wsadowy, który całkiem dobrze sobie z tym radzi.

spowoduje to tworzenie kopii zapasowych baz danych do poszczególnych plików we własnym katalogu każdego dnia

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
źródło