วิธีที่ดีที่สุดในการสำรองข้อมูลฐานข้อมูล PostgreSQL โดยอัตโนมัติคืออะไร


22

ฉันคิดว่ามันน่าเบื่อที่ต้องสำรองฐานข้อมูลทุกสัปดาห์ และฉันก็คิดว่าการสำรองข้อมูลรายสัปดาห์ควรเปลี่ยนเป็นการสำรองข้อมูลรายวัน หากฉันต้องทำสิ่งนั้นฉันไม่ต้องการทำด้วยตนเอง เป็นวิธีที่ดีที่สุดในการสำรองฐานข้อมูล PostgreSQL โดยอัตโนมัติทุกวันอย่างไร


หมายเหตุเล็กน้อย: การดัมพ์ db สามารถทำลายประสิทธิภาพใช้คลัสเตอร์และดัมพ์บนโหนดที่ไม่แอ็คทีฟ
neutrinus

คุณสามารถทำการสำรองข้อมูลตามกำหนดเวลาได้ด้วยความช่วยเหลือของเครื่องมือฟรีนี้postgresql-backup.com
Olek Nilson

คำถามถัดไป: คุณมีขนาดใหญ่แค่ไหนคุณมีกลไกการสำรองข้อมูลทั่วไปอย่างไร ตัวอย่างเช่นฉันไม่เคยสำรองข้อมูลด้วยตนเองเลย ติดตั้งตัวแทนของระบบสำรองข้อมูลของฉันเลือกองค์ประกอบที่จะสำรองใน UI กำหนดเวลาสำรองข้อมูล (ในกรณีของฉันสำหรับฐานข้อมูล: ทุก 5 นาที) .... เสร็จสิ้น แต่นั่นถือว่าเพียงพอแล้วที่เหมาะสมที่จะติดตั้งระบบที่เหมาะสม
TomTom

ฉันจะไม่เรียก postgresql-backup.com วิธีแก้ปัญหา "ฟรี" มันฟรีสำหรับฐานข้อมูล 2 แห่งแรกเท่านั้น ... @OlekNilson
Aidan Melen

คำตอบ:


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 switch (บรรทัด 27) เลิกใช้แล้วแทนที่ด้วย--column-inserts
https://wiki.postgresql.org/wiki/Deprecated_Features


10
+1 สำหรับสคริปต์ที่ดี
rkthkr

ฉันใช้สิ่งที่คล้ายกันมากกับ PreDumpCmd สำหรับ backuppc ยกเว้นว่าฉันไม่เข้ารหัสวันที่ในเส้นทางเนื่องจาก backuppc จัดการกับการเก็บสำเนาหลายชุด
David Pashley

2
สคริปต์ที่ยอดเยี่ยม แต่ฉันพบว่าฉันต้องปรับแต่ง regex เพื่อไม่ให้มีไพพ์และบรรทัดว่างเป็นชื่อฐานข้อมูล DBS=$($PSQL -l -t | egrep -v 'template[01]' | awk '{print $1}' | egrep -v '^\|' | egrep -v '^$')
s29

@ s29 ฉันคิดว่าดีกว่าที่จะใช้การสืบค้นโดยตรงแทนที่จะเป็น grep แฮ็คทั้งหมดเช่น: DBS = ($ ($ {PSQL}} -t -A -c "เลือกชื่อจาก pg_database โดยที่ datname ไม่ได้อยู่ใน ('template0', ' template1 ') "))
PolyTekPatrick

สุดยอดสคริปต์ - แล้วสิ่งนี้เปรียบเทียบกับบริการอย่าง ClusterControl อย่างไร
karns

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

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 Karpe

0

หากคุณต้องการสำรองข้อมูลทั้งคลัสเตอร์ด้วยการโหลดระบบน้อยที่สุดคุณสามารถ tar ไดเร็กทอรีรูทของคลัสเตอร์ 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
Peter Eisentraut

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
)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.