bestlong 怕失憶論壇

 

 

搜索
bestlong 怕失憶論壇 論壇 Database - 資料庫 PostgreSQL PostgreSQL 的熱備份和回復
查看: 6086|回復: 0
go

PostgreSQL 的熱備份和回復 [複製鏈接]

Rank: 9Rank: 9Rank: 9

1#
發表於 2006-9-13 14:50 |只看該作者 |倒序瀏覽 |打印
文章來源: http://www.cublog.cn/opera/showart.php?blogid=15722&id=85453

PostgreSQL 的 PITR 技术(Point-In-Time-Recovery)
-- Seamus Dean 2005-04-11 (at PostgreSQL-8.0.2 release)

为什么要写这篇文章?
因为我看了一下,国内所有的 PostgreSQL 教程都没有很详细的介绍该功能,而相反,国内的 Oracle 文章对这块非常的看重。虽然,PostgreSQL 的官方文档有一个章节是介绍这块内容的,但是写得太过‘文学’化。
的确,一个数据库的可靠性和完整性是非常重要的,否则,很难叫人们所接受它。

本文假设读者对 PostgreSQL 已经有基本的认识,如果你对 PostgreSQL 还完全不熟悉的话,建议你先去 http://www.postgresql.org 看看它的 Documentation.


作为最强大的开源数据库,PostgreSQL 拥有一切商业数据库所拥有的功能,甚至比商业数据库更好。在以前的版本中,它在数据恢复,可靠性方面做的不太好,但经过最近几年的发展,已经可以和 Oracle 媲美了。


在 PostgreSQL7 的时候就引入了 WAL(Write Ahead Logging)的概念,即预写日志,所有对数据库的更改,在更改之前必须写到该 LOG 中,这样,就算机器断电,PostgreSQL 也可以从该 LOG 中知道数据库在断电前做了什么操作,已经做到第几步了,这样保证了所有事务的完整性,但 PostgreSQL7 没有提供很好的灾难恢复机制,一旦数据库崩溃,除非你曾经对数据库作过 pg_dump 或者 file system level backup ,否则,你的数据将全部丢失,并且,就算你曾经对数据库做过备份,也只能恢复到你备份的那一刻的数据,这对一个生产数据库(特别是 24*7 生产库)来说,是无法容忍的。

PostgreSQL8 的推出,使 PostgreSQL 的稳定性和可靠性又迈出了划时代的一步。除了提供对 TableSpace 的支持外,PostgreSQL8 提供了支持时间点的恢复---PITR.
其基本原理和 Oracle 的热备份完全一样:

首先,对数据库在 file system level 做一个 backup (PostgreSQL 是首先用 pg_start_backup('label')命令,然后用 tar 直接 tar 整个 data 目录,假设命名为 base.tar, 然后 pg_stop_backup(); 结束热备。Oracle 首先是用 alter tablespace xxx begin backup, 然后直接 cp 数据文件);

然后,备份相关的配置文件(PostgreSQL 只需备份 postgresql.conf, pg_hba.conf, pg_ident.conf 就可以了,其实,前面的 tar 已经将这些文件备份了,Oracle 需要 alter database backup control file......);

最后,备份WAL(
可以设置 postgresql.conf 中的 archive_command,该命令可以让 PostgreSQL8 自动将需要的归档的日志文件备份的其他地方中。

但是注意:如果你是让 PostgreSQL8 调用 archive_command 来备份WAL的话,可能根本就做不到 PITR,我做过实验,如果依靠 base.tar 和 archive_command产生的 WAL 其实只能恢复到最后一个 archive_command 保存的 WAL 的数据,pg_xlog/ 下面可能还有数据,如果 PostgreSQL8 的数据目录彻底损坏的话,还是会丢失数据,所以,我建议,在写数据备份脚本的时候,最好将 pg_xlog/ 下面的 WAL 也一起备份,见下面的 cpArch.sh。
)。

如果数据库崩溃,我们就可以使用热备产生的 base.tar 和 archive_command 产生的 WAL 和我们自己备份的 WAL(pg_xlog) 来进行数据库的
recovery.

下面举例来说明:
我的 PostgreSQL 运行在:/home/pgsql/ 下面
数据目录在:/home/pgsql/database/
将热备数据文件备份到 /disk3/PostgreSQL/base/ 下面
将 WAL 备份到 /disk3/PostgreSQL/archives/ 下面

postgresql.conf 中定义了如下的 archive_command:
archive_command = 'cp -f %p /disk3/PostgreSQL/archives/%f'
该命令会将 PostgreSQL 产生的 WAL cp 到 /disk3/PostgreSQL/archives/ 中。

我的热备脚本如下:
(1)为了使丢失的数据在一分钟之内,在 crontab 中每分钟将 pg_xlog/ 下面的WAL backup 到 /disk3/PostgreSQL/archives/。

crontab:
*/1 * * * * /home/pgsql/bin/cpArch.sh

cpArch.sh:
#!/bin/sh

cp -f /home/pgsql/database/pg_xlog/[0-9]* /disk3/PostgreSQL/archives/


(2)编写热备脚本 hotBackup.pl (我用perl):
#!/usr/bin/perl

#############################################################
# hotBackup.pl
# Use to hot backup the PostgreSQL database.
# Author:Seamus Dean
# Date:2005-04-11
##############################################################

my($datadir) ="/home/pgsql/database";
my($bindir) ="/home/pgsql/bin";
my($backupdir) ="/disk3/PostgreSQL/base";
my($receiver) ="ljh13\@sina.com.cn";

sub begin_backup()
{
open(PSQL,"|$bindir/psql") or mail_user("begin backup error.") && exit(100);
print PSQL "select pg_start_backup('backupnow');\n";
close(PSQL);

}

sub end_backup()
{
open(PSQL,"|$bindir/psql") or mail_user("end backup error.") && exit(100);
print PSQL "select pg_end_backup();\n";
close(PSQL);
}


sub do_backup()
{
system("/bin/tar cvf base.tar $datadir");
system("/bin/mv -f base.tar $backupdir/");
}


sub mail_user()
{
my($msg) =@_;
open(MAIL,"|/bin/mail -s backup-result $receiver") or die("can not talk to:mail command.\n");
print MAIL $msg;
close(MAIL);
}

###################################
# tell psql begin our backup
###################################
&begin_backup();

###################################
# do tar
###################################
&do_backup();

####################################
# tell psql end backup
####################################
&end_backup();

####################################
# mail the user about the result
####################################
&mail_user("PostgreSQL backup successfully.");


到这里,备份脚本基本上就完了,你可以将 hotBackup.pl 放在 crontab 中周期性的执行。

就算 /home/pgsql/database 目录彻底崩溃,我们可以像下面这样迅速恢复到1分钟内的数据:
#cp /disk3/PostgreSQL/base/base.tar ./
#tar xvf base.tar
#cd database/
#vi recovery.conf

输入如下内容:
restore_command='cp /disk3/PostgreSQL/archives/%f "%p"'
然后将 /home/pgsql/database/pg_xlog/ 下面的 WAL 清空。
启动 PostgreSQL, 我们可以看到如下的 LOG 信息:
LOG: could not create IPv6 socket: Address family not supported by protocol
LOG: database system was interrupted at 2005-04-11 23:13:28 PDT
LOG: starting archive recovery
LOG: restore_command = "cp /disk3/PostgreSQL/archives/%f "%p""
cp: cannot stat `/disk3/PostgreSQL/archives/00000001.history': No such file or directory
LOG: restored log file "00000001000000000000002E.008EFCAC.backup" from archive
LOG: restored log file "00000001000000000000002E" from archive
LOG: checkpoint record is at 0/2E8EFCAC
LOG: redo record is at 0/2E8EFCAC; undo record is at 0/0; shutdown FALSE
LOG: next transaction ID: 5271; next OID: 6351357
LOG: automatic recovery in progress
LOG: redo starts at 0/2E8EFCE8
LOG: restored log file "00000001000000000000002F" from archive
LOG: restored log file "000000010000000000000030" from archive
LOG: restored log file "000000010000000000000031" from archive
LOG: restored log file "000000010000000000000032" from archive
LOG: restored log file "000000010000000000000033" from archive
LOG: restored log file "000000010000000000000034" from archive
LOG: restored log file "000000010000000000000035" from archive
LOG: restored log file "000000010000000000000036" from archive
LOG: restored log file "000000010000000000000037" from archive
LOG: restored log file "000000010000000000000038" from archive
LOG: restored log file "000000010000000000000039" from archive
LOG: restored log file "00000001000000000000003A" from archive
LOG: restored log file "00000001000000000000003B" from archive
LOG: restored log file "00000001000000000000003C" from archive
LOG: restored log file "00000001000000000000003D" from archive
LOG: restored log file "00000001000000000000003E" from archive
LOG: restored log file "00000001000000000000003F" from archive
LOG: restored log file "000000010000000000000040" from archive
LOG: restored log file "000000010000000000000041" from archive
LOG: restored log file "000000010000000000000042" from archive
LOG: restored log file "000000010000000000000043" from archive
LOG: restored log file "000000010000000000000044" from archive
LOG: restored log file "000000010000000000000045" from archive
LOG: restored log file "000000010000000000000046" from archive
LOG: restored log file "000000010000000000000047" from archive
LOG: restored log file "000000010000000000000048" from archive
LOG: restored log file "000000010000000000000049" from archive
LOG: restored log file "00000001000000000000004A" from archive
LOG: restored log file "00000001000000000000004B" from archive
LOG: restored log file "00000001000000000000004C" from archive
LOG: record with zero length at 0/4C2BABE4
LOG: redo done at 0/4C2BABA8
LOG: restored log file "00000001000000000000004C" from archive
LOG: archive recovery complete
LOG: database system is ready


显示数据已经成功恢复。/home/pgsql/database/ 下面的 recovery.conf 会变为:recovery.done.

结论:
PostgreSQL8 的 PITR 已经做得非常的成功,完全有可能替代 Oracle, Sql Server 而成为企业的首选。所以,我们玩 PostgreSQL 的兄弟们,一定要对它有信心!
我是雪龍
http://blog.bestlong.idv.tw
http://www.bestlong.idv.tw
‹ 上一主題|下一主題

Archiver|怕失憶論壇

GMT+8, 2024-4-26 20:11 , Processed in 0.014510 second(s), 11 queries .

Powered by Discuz! X1.5

© 2001-2010 Comsenz Inc.