自动化PostgreSQL数据库备份的最佳方法是什么?


22

我发现每周必须备份数据库很麻烦。而且我还认为每周备份应该转换为每日备份。如果必须这样做,我不想手动进行。每天自动执行PostgreSQL数据库备份的最佳方法是什么?


小提示:转储数据库可能会降低性能,使用群集并在非活动节点上转储。
neutrinus

您可以借助此免费工具postgresql-backup.com
Olek Nilson,2016年

下一个问题:您的规模有多大,您拥有哪种常规的备份机制。例如,我从不手动备份任何内容。安装我的备份系统的代理,选择要在UI中备份的元素,计划备份(对于我而言,对于数据库:每5分钟)....完成。但这假设有足够的理由安装适当的系统。
TomTom

我不会将postgresql-backup.com称为“免费”解决方案。它仅对前两个数据库是免费的... @OlekNilson
Aidan Melen

Answers:


40

与您可以自动执行的其他重复性任务相同,您可以编写脚本进行备份,然后设置cron作业来运行该备份。

例如,如下所示的脚本:

(注意:它必须以postgres用户或具有相同privs的任何其他用户身份运行)

#! /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,2009年

我使用与Backuppc的PreDumpCmd非常相似的东西,除了我不将日期编码到路径中,因为backuppc处理保留多个副本。
David Pashley 09年

2
很棒的脚本,但是我发现我需要调整正则表达式,使其不包含管道和空行作为数据库名称。 DBS=$($PSQL -l -t | egrep -v 'template[01]' | awk '{print $1}' | egrep -v '^\|' | egrep -v '^$')
2013年

@ s29我认为最好使用直接查询而不是所有grep骇客,例如:DBS =($($ {PSQL} -t -A -c“从pg_database中选择datname,其中datname不在('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使行永远不会被分割。恢复失败的调试更加容易。
Gianluca Della Vedova 2014年

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创建的还原单个表的脚本
Ashish

0

如果您想以最小的系统负载备份整个集群,则只需简单地将PostgreSQL集群的根目录放在tar中即可。例如:

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归档,则此方法将无效。
Peter Eisentraut 2010年

0

万一有人在没有cygwin的帮助下将postgres备份在Windows机器上,我有一个批处理文件,可以很好地完成工作。

每天将数据库备份到其自己目录中的单个文件中

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
)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.