Какой лучший способ автоматизировать резервное копирование баз данных PostgreSQL?

22

Я считаю утомительным делать резервные копии баз данных каждую неделю. И я также думаю, что еженедельные резервные копии должны быть превращены в ежедневные резервные копии. Если бы мне пришлось это сделать, я бы не хотел делать это вручную. Какой лучший способ автоматизировать резервное копирование баз данных PostgreSQL ежедневно?

Рэнделл
источник
Небольшое примечание: сброс базы данных может снизить производительность, использовать кластер и создавать дамп на неактивных узлах.
нейтринус
Вы можете делать резервные копии по расписанию с помощью этого бесплатного инструмента postgresql-backup.com
Olek Nilson
Следующий вопрос: какой у вас размер, какой механизм резервного копирования у вас есть. Например, я никогда ничего не копирую вручную. Установите агент моей системы резервного копирования, выберите элементы для резервного копирования в пользовательском интерфейсе, запланируйте резервное копирование (в моем случае для баз данных: каждые 5 минут) .... Закончено. Но это предполагает наличие достаточного количества, чтобы иметь смысл установить правильную систему.
TomTom
Я бы не назвал postgresql-backup.com «бесплатным» решением. Это бесплатно только для первых 2 баз данных ... @OlekNilson
Эйдан Мелен

Ответы:

40

так же, как вы делаете для любой другой повторяющейся задачи, которая может быть автоматизирована - вы пишете скрипт для резервного копирования, а затем настраиваете задачу cron для ее запуска.

например, скрипт, подобный следующему:

(Примечание: он должен запускаться от имени пользователя postgres или любого другого пользователя с такими же привилегиями)

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

РЕДАКТИРОВАТЬ:
pg_dumpall -D переключатель (строка 27) устарел, теперь заменен на --column-inserts
https://wiki.postgresql.org/wiki/Deprecated_Features

саз
источник
10
+1 за отличный сценарий
rkthkr
Я использую что-то очень похожее в качестве PreDumpCmd для backuppc, за исключением того, что я не кодирую дату в пути, так как backuppc имеет дело с сохранением нескольких копий.
Дэвид Пашли
2
Отличный сценарий, но я обнаружил, что мне нужно настроить регулярное выражение так, чтобы оно не включало в себя имена каналов и пустые строки. DBS=$($PSQL -l -t | egrep -v 'template[01]' | awk '{print $1}' | egrep -v '^\|' | egrep -v '^$')
с29
@ s29 Я думаю, что лучше использовать прямой запрос вместо всей этой хакерской программы grep, например: DBS = ($ ($ {PSQL} -t -A -c "выбрать имя данных из базы данных pg_database, где имя данных отсутствует ('template0', ' template1 ') "))
PolyTekPatrick
Потрясающий сценарий - как это можно сравнить с такими сервисами, как ClusterControl?
Карнс
7
pg_dump dbname | gzip > filename.gz

Перезагрузить с

createdb dbname
gunzip -c filename.gz | psql dbname

или

cat filename.gz | gunzip | psql dbname

Использование split. Команда splitпозволяет вам разбить вывод на части, приемлемые по размеру для базовой файловой системы. Например, чтобы сделать куски по 1 мегабайту:

pg_dump dbname | split -b 1m - filename

Перезагрузить с

createdb dbname
cat filename* | psql dbname

Вы могли бы бросить один из тех, кто в /etc/cron.hourly

Источник: http://www.postgresql.org/docs/8.1/interactive/backup.html#BACKUP-DUMP-ALL

Ник Андерсон
источник
Разделение файла - отличная идея. Лучше разбить дамп, используя split -C, чтобы строка никогда не разбивалась. Отладка неудачного восстановления проще.
Джанлука Делла Ведова
3

Какие бы команды вы ни вводили «вручную», запишите их в скрипт и поместите вызов этого скрипта в cron или любой другой планировщик, который вы используете.

Конечно, вы можете сделать сценарий более причудливым, но в целом, я думаю, вы доберетесь до него - начните с простого, а потом уточните.

Самый простой из возможных сценариев:

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

Сохраните его как /home/randell/bin/backup.sh и добавьте в cron:

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

источник
Если используется pg_dumpall, возможно ли восстановить из него одну таблицу или она восстановит все сразу? Можете ли вы поделиться сценарием для восстановления одной таблицы, созданной с помощью dumpall
Ашиш Карпе
0

Если вы хотите сделать резервную копию всего кластера с минимальной загрузкой системы, вы можете просто заархивировать корневой каталог кластера postgresql. например:

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

это основная часть моего резервного скрипта.

подветренный
источник
1
Нет, это не сработает, если у вас также не включено архивирование WAL.
Питер Айзентраут
0

на случай, если кто-то должен будет сделать резервную копию своих postgres на машине с Windows без помощи cygwin и т. д., у меня есть пакетный файл, который делает эту работу довольно хорошо.

это будет резервировать базы данных в отдельные файлы в своем собственном каталоге каждый день

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
источник