Apa cara terbaik untuk mengotomatiskan back-up database PostgreSQL?

22

Saya merasa perlu untuk membuat cadangan basis data setiap minggu. Dan saya juga berpikir cadangan mingguan harus diubah menjadi cadangan harian. Jika saya harus melakukan itu, saya tidak ingin melakukannya secara manual. Apa cara terbaik untuk mengotomatiskan pencadangan database PostgreSQL setiap hari?

Randell
sumber
Catatan kecil: membuang db dapat mematikan kinerja, menggunakan cluster dan membuang pada node yang tidak aktif.
neutrinus
Anda dapat membuat cadangan terjadwal dengan bantuan alat gratis ini postgresql-backup.com
Olek Nilson
Pertanyaan berikutnya: Seberapa besar Anda, mekanisme cadangan umum apa yang Anda miliki. Misalnya, saya tidak pernah mencadangkan apa pun secara manual. Instal agen sistem cadangan saya, pilih elemen yang akan didukung di UI, jadwalkan pencadangan (dalam kasus saya untuk basis data: setiap 5 menit) .... selesai. Tetapi itu mengasumsikan memiliki cukup bahwa masuk akal untuk menginstal sistem yang tepat.
TomTom
Saya tidak akan menyebut postgresql-backup.com solusi "gratis". Ini hanya gratis untuk 2 basis data pertama ... @OlekNilson
Aidan Melen

Jawaban:

40

sama seperti yang Anda lakukan untuk tugas berulang lainnya yang dapat diotomatisasi - Anda menulis skrip untuk melakukan pencadangan, dan kemudian menyiapkan tugas cron untuk menjalankannya.

skrip seperti berikut ini, misalnya:

(Catatan: harus dijalankan sebagai pengguna postgres, atau pengguna lain dengan privs yang sama)

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

EDIT:
pg_dumpall -D switch (line 27) sudah usang, sekarang diganti dengan --column-inserts
https://wiki.postgresql.org/wiki/Deprecated_Features

cas
sumber
10
+1 untuk skrip hebat
rkthkr
Saya menggunakan sesuatu yang sangat mirip dengan PreDumpCmd untuk backuppc, dengan pengecualian bahwa saya tidak menyandikan tanggal ke path, karena backuppc berurusan dengan menyimpan banyak salinan.
David Pashley
2
Script yang bagus, tetapi saya menemukan saya perlu mengubah regex sehingga tidak menyertakan pipa dan garis kosong sebagai nama basis data. DBS=$($PSQL -l -t | egrep -v 'template[01]' | awk '{print $1}' | egrep -v '^\|' | egrep -v '^$')
s29
@ s29 Saya pikir lebih baik menggunakan kueri langsung daripada semua peretasan grep, seperti: DBS = ($ ($ {PSQL} -t -A -c "pilih datname dari pg_database di mana datname tidak berada di ('template0', ' template1 ') "))
PolyTekPatrick
Script yang luar biasa - jadi bagaimana ini dibandingkan dengan layanan seperti ClusterControl?
Karns
7
pg_dump dbname | gzip > filename.gz

Muat ulang dengan

createdb dbname
gunzip -c filename.gz | psql dbname

atau

cat filename.gz | gunzip | psql dbname

Gunakan split. The splitperintah memungkinkan Anda untuk membagi output menjadi potongan-potongan yang dapat diterima dalam ukuran ke sistem file yang mendasari. Misalnya, untuk membuat potongan 1 megabyte:

pg_dump dbname | split -b 1m - filename

Muat ulang dengan

createdb dbname
cat filename* | psql dbname

Anda bisa melemparkan salah satunya /etc/cron.hourly

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

Nick Anderson
sumber
Memisahkan file adalah ide bagus. Lebih baik untuk membagi dump, menggunakan split -C, sehingga garis tidak pernah terpecah. Men-debug pemulihan yang gagal lebih mudah.
Gianluca Della Vedova
3

Apa pun perintah yang Anda keluarkan "dengan tangan", - tulislah ke skrip, dan panggil skrip ini di cron atau penjadwal apa pun yang Anda gunakan.

Anda tentu saja dapat membuat skrip lebih mewah, tetapi secara umum, saya pikir Anda akan sampai di sana - mulai dari yang sederhana, dan kemudian perbaiki.

Skrip yang paling sederhana:

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

Simpan sebagai / home /randell / bin/backup.sh, tambahkan ke cron:

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

sumber
JIKA pg_dumpall digunakan, apakah mungkin untuk mengembalikan tabel tunggal darinya atau akan mengembalikan semuanya sekaligus? dapatkah Anda berbagi skrip untuk memulihkan satu tabel yang dibuat dengan menggunakan dumpall
Ashish Karpe
0

Jika Anda ingin mem-backup seluruh cluster dengan beban sistem minimal, Anda bisa dengan mudah menar direktori root dari cluster postgresql. sebagai contoh:

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

itulah bagian terbesar dari skrip cadangan saya.

lee
sumber
1
Tidak, ini tidak berfungsi jika Anda tidak mengaktifkan pengarsipan WAL.
Peter Eisentraut
0

jika ada orang yang membuat cadangan postgres mereka pada mesin windows tanpa bantuan cygwin dll saya punya file batch yang melakukan pekerjaan dengan cukup baik.

ini akan membuat cadangan database ke file individual di direktori itu sendiri setiap hari

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
sumber