PostgreSQL 的热备和恢复
莫奕
|
1#
莫奕 发表于 2006-08-22 00:26
PostgreSQL 的热备和恢复
为什么要写这篇文章?
因为我看了一下,国内所有的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,Sqlserver 而成为企业的首选。所以,我们玩PostgreSQL的兄弟们,一定要对它有信心! |