分类: LINUX
2009-05-11 09:08:33
第七章:备份与恢复
7.1备份与恢复概述
常见故障类型:语句失败、用户进程失败、用户错误、实例失败、介质故障、网络故障。
7.2备份方法
n
逻辑备份
n
物理备份
7.3恢复原理
如果在恢复时我们有足够的归档日志和在线重做日志,那么通过恢复一个全备份,应用归档日志和重做日志,最终数据库就可以实现完全恢复。
7.4数据库的运行模式
n
归档模式(archivelog)
n
非归档模式(noarchivelog)
获取当前数据库的归档状态:
SQL> archive log list;
简要步骤:
n
修改必要的初始化参数
n
以immediate方式关闭数据库
n
启动实例到mount状态
n
更改运行模式并打开数据库
(1) 修改初始化参数。和归档相关的几个主要参数如下:
n
log_archive_start:用于定义是否启动自动归档
n
log_archive_format:用于定义归档文件格式,可以采用缺省值
n
log_archive_dest:用于指定归档路径
如果数据库使用的是pfile,则可以直接修改,如果用的是spfile文件,则可以通过命令修改:
SQL> show parameter spfile;
SQL> alter system set log_archive_dest=’/opt/oracle/oradata/’;
SQL> alter system set log_archive_start=true scope=spfile;
(2) 关闭数据库
SQL> shutdown immediate;
(3) 启动数据库到mount状态
SQL> startup mount;
(4) 启用或停止归档模式。
SQL> alter database archivelog;
SQL> alter database noarchivelog;
在oracle
7.5oracle
查看闪回恢复区参数
SQL> show parameter db_recover;
db_recovery_file_dest
db_recovery_file_dest_size
以下几类主要文件可以在闪回区存放:
n
控制文件
n
归档的日子文件
n
闪回日志
n
控制文件和spfile自动备份
n
Rman备份集
n
数据文件拷贝
很多朋友习惯通过手工清除文件的方式释放空间,但是数据库无法得知这个空间释放。可以查看视图(v$recovery_file_dest)。
SQL> select * from v$recovery_file_dest;
如果是删除归档日志文件,那么正确的做法应该是使用Rman登陆数据库进行crosscheck,再删除过期的备份,空间才能得到释放。常用命令如下:
RMAN> crosscheck archivelog all;
RMAN> delete expired archivelog all;
修改闪回区大小
SQL> alter system set db_recovery_file_dest_size=
7.6逻辑备份与恢复
n
EXP导出与字符集
导出客户端的字符集的设置会影响导出数据,所以应该设置导出客户端字符集和数据库一致。在Windows的命令行可以如下设置:
C:\set nls_lang=AMERICAN_AMERICA.ZHS16GBK
在linux上可以设置
$export NLS_LANG=AMERICAN_AMERICA.ZHS16GBK
n
带查询子句的部分导出
以下是一个简单的范例:
C:\>
exp eygle/eygle@dana file=test.dmp
tables=tquery query=’where object_id “<”
n
参数文件的使用
$ cat parfile.lst
userid=eygle/eygle
file=test.dmp
tables=tquery
query=”where object_id <
$ exp parfile=parfile.lst
n
使用通配符进行模糊导出
$ exp eygle/eygle tables=e% file=a.dmp
这样,以字母E开头的表都被导出了。
n
排除部分表的导出
n
按日期区分文件名称的导出
很多时候,在导出备份时,我们希望在文件名中加入日期变量,以区分不同日期的导出文件。
以下介绍两种方法
(1) 通过数据库查询获取日期。
通过数据库查询可以获得需要的日期格式,在Windows上可以编写两个文件用于完成备份,一个是可执行的批处理文件,名称为startbak.bat,可以包含如下内容:
echo off
set oracle_sid=eygle
sqlplus eygle/eygle @expbydt.sql
第二个文件是expbydt.sql脚本
column today new_val dt
select to_char( sysdate,’ddmmyyyy’ ) today from dual;
host exp userid=eygle/eygle file=exp_eygle_&dt..dmp
log=exp_eygle_&dt..log
exit
准备好了这两个文件之后,就可以通过命令行运行starbak.bat来执行逻辑备份了;
D:\backup>startbak.bat
D:\backup>echo off
(2) 通过操作系统获取日期
在Windows可以通过如下命令获得:
D:\backup>echo
%date:~0.10%
可以通过一个名为expbdt.bat的批处理文件来执行导出操作:
echo off
set oracle_sid=eygle
exp userid=eygle/eygle full=y file=d:\backup\exp_eygle_%date:~0.10%.dmp log=d:\backup\exp_eygle_%date:~0.10%.log
执行的结果和上面的方法类似:
D:\backup>expdbt.bat
在linux上的时间定义就显得更为简单:
exp eygle/eygle file=eygle_`date +%Y%M%d`
n
导入数据到不同的表空间
很多朋友在进行数据迁移时,希望把数据导入不同于系统的表空间,在导入之后却往往发现,数据导入了原表空间。这是因为如果缺省的原用户具有unlimited tablespace的权限,那么导入时会按照原来的位置导入数据,即导入到原表空间。
以下时一个测试范例,目标时将jive用户的数据导入到bjbbs用户下,就可以通过fromuser和touser参数来将数据导入到不同的用户下:
$ imp bjbbs/passswd file=bj_bbs.dmp fromuser=jive touser=bjbbs
grants=n;
但是导入完成发现,新导入的数据被存储在jive用户的缺省表空间USER中
SQL> select table_name,tablespace_name from user_tables;
Drop掉用户,重新创建并回收用户unlimited tablespace权限:
SQL> create user
bjbbs identified by passwd
2
default
tablespace bjbbs
3
temporary
tablespace temp
4
/
SQL> grant connect ,resourse to bjbbs;
SQL> grant dba to bjbbs;
SQL> revoke unlimited
tablespace from bjbbs;
SQL> alter user bjbbs quota 0 on users;
SQL> alter user bjbbs quota unlimited on bjbbs;
重新导入数据:
$ imp bjbbs/passswd file=bj_bbs.dmp fromuser=jive touser=bjbbs
grants=n;
n
使用indexfile进行导入
在有些特殊的情况下(如创建对象时强制指定非缺省表空间),以上的方法可能还是不能奏效,那么IMP工具还有另外一个参数可以使用,这个参数时INDEXFILE,当执行导入时指定参数INDEXFILE后,系统将创建表空间和索引等语句写到一个文件,通过编辑这个文件,就可以修改对象的创建语句,将表空间更改为希望的目标表空间,然后运行这个脚本完成对象创建,之后导入数据时至需要指定INGNORE=Y忽略创建错误,Oracle就可以将数据导入到正确的表空间,如果需要变更用户,则还需要指定FROMUSER和TOUSER参数。
来看一个简单的测试,通过indexfile来执行一次导入(数据并不会被导入)
$ imp eygle/eygle
file=test.dmp indexfile=test.idx rows=n
$ cat
text.idx
缺省地,所有数据被标记为注释REM,修改TABLESPACE信息并去掉REM注释后该文件就可以SQL*PLUS调用来创建对象了。
n
关于数据泵的概述
数据泵主要工作在服务器端,可以通过并行的方式快速装入或卸载数据,而且可以在运行过程中调整并行的程度,以加快备份或减少资源耗用。
n
数据泵使用
与EXP不同,EXPDP增加了一个主要的新的参数:DIRECTORY
这个参数是用来定义一个路径,前面我们提到,数据泵主要在server端工作,导出文件需要写出到server端本地目录,这个DIRECTORY就对应的是server的路径。
可以自己创建一个DIRECTORY,也可以使用默认缺省的路径
SQL> create or replace directory expdir as ’d:\oracle\expdir’
SQL> select * from dba_directories where directory_name=’EXPDIR’
然后可以对相应的用户进行授权:
SQL> grant read,write on directory expdir to eygle;
接下来可以通过EXPDP来导出操作了:
C:\>expdp
eygle/eygle dumpfile=eygle.dmp
directory=expdir;
n
EXPDP/IMPDP的停止与重启
EXPDP/IMPDP的本质在于,通过API调用,把传统的EXP/IMP类交互模式的操作,转变为数据库内部的job任务,从而实现了任务的可中止与重启。
在数据库内部,重启动还依赖于另外一个数据结构MT(master table ,任务主表),该表用于记录导入导出任务的进度。
接下来通过实例来看一下这几个参数的作用。
首先启动EXPDP执行导出操作,这里指定一个job_name,这个名称将是数据库中创建MT表的名称。
$ expdp eygle/eygle directory=dpdata dumpfile=full.dmp full=y
job_name=expfull
在这里,可以通过Ctrl+C,退出当前交互模式,此时支持status等查看命令。
Export> status
如果此时要停止该任务,可以发出stop_job命令:
Export> stop_job
进入到数据库,可以看到为执行导出任务为所创建的MT表
SQL> select * from tab where tname=’EXPFULL’;
接下来可以通过命令行再次连接到这个任务:
$expdp eygle/eygle attach=expfull
通过 start_job命令重启:
Export> start_job
n
EXPDP排除部分对象的导出
以下是solaris上Exclude 参数的使用范例,需要转义符“\”
$ expdm \’/ as sysdba\’
directory=DATA_PUMP_DIR schemas=rman dumpfile=expdp_rman.dmp EXCLUDE=TABLE:\”in\(DB\)”\;
最简单的方式仍然是将参数写入到一个参数文件来调用,这样可以避免复杂的参数转义
$cat parfile.par
directory=DATA_PUMP_DIR
schemas=rman
dumpfile=expdp_rman.dmp
INCLUDE=TABLE:”IN(‘DB’,’TS’)”
然后调用这个参数文件来执行导出:
$expdp \’/ as sysdba\’ parfile=parfile.par
7.7物理备份与恢复
以下几个查询在备份之前执行,以确认数据库文件以及存储路径
SQL> select name from v$datafile;
SQL> select member from v$logfile;
SQL> select name from v$controlfile;
冷备份步骤:
n
正常关闭数据库
n
备份所有重要的数据到备份目录
n
完成备份后启动数据库
(1) 用户管理的热备份
用户管理的热备份通常步骤:
n
在备份之前需要显示的发出Begin Backup的命令
n
在操作系统拷贝备份文件
n
发出end backup命令通知数据库完成备份
n
备份归档日志文件
常见备份过程如下,这里以一个表空间的备份为例:
alter tablespace system begin backup;
host copy
E:\ORACLE\ORADATA\EYGLE\SYSTEM01.DBF e:\oracle\orabak\SYSTEM01.DBF;
Alter tablespace system end backup;
当备份被激活时,可以通过v$backup视图来检查表空间的备份情况:
SQL> select * from v$backup
需要注意的是,当表空间置于热备份模式下,表空间数据文件头的检查点会被冻结,当热备份完成,发出 end backup命令,表空间数据文件检查点被重新同步,恢复更新:
(2) 额外Redo的生成
在使用Begin backup开始备份时,数据库会产生了比平常更多的日志,也就会产生更多的归档。这是因为在热备期间,oracle为了解决SPLIT BLOCK的问题,需要在日志文件中记录修改的行所在的数据块的前镜像,而不仅仅是修改信息
当拷贝数据文件的同时,数据库正好向数据文件写数据。这使得拷贝的文件中包含这样的database block,它的一部分来自于写操作之前,另一部分来自写操作之后。对于数据库来说,这个database blok本身并不一致,而是一个分裂块SPLIT BLOCK.这样的分裂块在恢复时并不可用。所以在热备状态下,对于变更的数据,oracl需要在日志记录整个变化的数据库的前镜像,这样如果在恢复的时候,数据文件中出现分裂块,oracle就可以通过日志文件中的数据库的前镜像覆盖备份,以完成恢复。
来看下测试,首先通过SYS用户连接数据库,确认SCOTT用户连接信息及日志信息:
SQL> alter system switch logfile;
SQL> select * from v$log;
SQL> select sid.serial# ,username from v$session;
分裂块产生的根本原因在于备份过程中引入了操作系统工具如cp工具,操作系统工具无法保证oracle数据块的一致性。如果使用RMAN备份,由于Rman可以通过反复读取获得一致的blok,从而避免SPLIT BLOCK的生成,所以不会产生额外的REDO,所以建议在备份时,应该尽量采用RMAN备份。
(3) 定制自适应的热备份脚本
以下是在生产库中经过实践的脚本范例:
首先看看crontab的定义
$crontab -l
30 2 * * 0-6 /opt/oracle/tools/hotbackup/startbak.sh
整个备份是通过一个叫startbak.sh的脚本启动的,这个脚本的主要内容如下:
Week=`date +”%w”`
Today=`date +”%m%d”`
Ps –ef|grep dbw0_$ORACLE_SID|grep –v grep >> /dev/null
If [ $? –eq 0 ];then
If [ $week = “
$SH_HOME/genbaksql.sh
Else
$SH_HOME/dobakarch.sh
Fi
fi
如果周一则执行全备份,否则执行归档日志备份。
Genbaksql.sh这个脚本的主体部分包含如下语句:
Select ‘PROMPT Begin
backup tablespace’
||tablespace_name
|| ‘.’ || file_name ||CHR(10)
||‘alter
tablespace’||tablespace_name||’begin backup;’||CHR(10)
||‘! cp’||file_name||’$BACKUP_FILE’||CHR(10)
||’alter tablespace’||tablespace_name||’end
backup;’||CHR(10)
From dba_data_files
Where status=’AVAILBLE’;
(4) Oracle
在oracle
SQL> alter database begin backup;
SQL> alter database end backup;
(5) 通过归档逐步恢复以缩短数据迁移时间
很多时候你可能会遇到这样的情况:一个大型数据库在同版本、同平台、异地异机的迁移,但是只有很少的停机时间,这看起来充满困难,但可以通过各种方法来缩短停机时间。在此情况下,可以通过一个热备份,应用归档恢复数据库到一个一致的状态,此时数据库可以被只读打开。之后可以继续应用归档进行恢复,最后只需要短时间停机,复制原数据库的在线日志和归档日志,控制文件到新库中,进行恢复,此时只需要极短时间即可完成恢复,这个方法只能适合在同平台的迁移过程中使用。
以下是一个示范步骤:
n
确定源数据库信息
查询源数据库归档情况,确认归档日志:
SQL> select name from v$archived_log;
归档当前日志
SQL> alter system switch logfile;
n
备份数据库
对源数据库进行备份,以下是简单的参考脚本:
Alter tablespace system begin backup;
Host copy E:\ORACLE\SYSTEM01.DBF e:\oracle\orabak\SYSTEM01.DBF
Alter tablespace system end backup;
执行备份
SQL>
@e:\a.sql
n
更改数据并归档部分日志
为了测试目的,再修改部分数据,并继续归档,数据库服务继续对外提供:
SQL> insert into eygle.test select * from eygle.test;
SQL> commit
SQL> alter system switch logfile;
SQL> insert into eygle.test select * from eygle.test;
SQL> commit
SQL> shutdown immediate;
n
执行恢复
在迁移过程中,可以将备份文件传输到目标主机,在目标主机恢复备份的数据文件,启动数据库:
SQL> startup mount
可以使用备份的控制文件执行恢复
SQL> recover database using backup controlfile until cancel;
应用了所有归档日志文件之后,可以将数据库以只读打开
SQL> alter database open read only;
因为源数据库的修改还在继续,可以关闭数据库,然后重新启动,应用归档日志,再次执行数据恢复:
SQL> shutdown immediate;
SQL> startup mount
SQL> recover database using backup controlfile until cancel;
恢复完成之后,数据库仍然以只读打开,进行数据确认,这样不断应用归档日志,迁移数据库可以和主数据库不断进行数据同步,在迁移停机时间到来时,就可以通过将源数据库所有日志归档,传输到迁移数据库应用,完成恢复,或者直接应用重做日志,完成恢复:
SQL> alter database open resetlogs;
(6) 用户管理备份的完全恢复
n
假定数据文件丢失,但是还有当前的控制文件和日志文件
首先restore数据文件到原有目录
此时如果尝试启动数据库,oracle就会提示需要介质恢复,这是根据控制文件和数据文件头的信息进行判断的
正常情况下可以先启动数据库到mount状态,然后开始恢复:
SQL> startup mount;
因为我们拥有最新的控制文件和所有归档及在线日志文件,所以简单通过一条命令执行恢复:
SQL> recover database;
(1) RMAN的备份保留策略
查看rman参数配置:
RAMN>
show all;
查看废弃的备份
RAMN>
report obsolete
设置REDUNDANCY设置为2
RAMN>
configure retention policy to redundancy 2;
删除过期备份
RAMN>delete
nopromt obsolete;
(2) 常用的crosscheck命令
当我们以手工方式删除了某些备份之后,RMAN将无法找到这些文件,但是这些文件在RMAN的备份记录中仍然存在。为了去除这些记录,可以参考以下实例:
RMAN>
crosscheck backup;
RAMN>
delete expired backup;
当手动删除了归档日志之后,可以用类似的命令来验证归档日志文件:
RMAN>
crosscheck archivelog all
RAMN>
delete noprompt expired archivelog all;
(3) 使用nocatalog方式进行数据库备份
可以通过如下方式设置控制文件自动备份:
C:\>rman
target /
RMAN>
configure controlfile autobackup on;
这个设置可以在RMAN中查询:
RMAN>
show controlfile autobackup;
也可以在数据库中通过如下方式查询:
SQL>
select * from v$rman_configuration;
注意下备份路径,由于在
这里自动备份的控制文件缺省的命名规则:
c-IIIIIIIII-YYYYMMDD-QQ
其中c是控制文件,I是DBID,YYYYMMDD是时间戳,QQ取决于序号00-FF。
我们再来看一个全备份的处理:
RMAN> backup database tag=eygle090509
由于使用控制文件作为备份信息存储池,在完成备份后会写控制文件,这个写操作进而会触发控制文件的自动备份。
有了自动备份之后,在发生灾难后就可以使用自动备份恢复spfile文件和控制文件,恢复参数文件可以使用如下命令(通常恢复到一个临时目录下,以免覆盖当前文件,确认后再转移到缺省目录)。恢复spfile文件可以参考如下步骤:
RMAN> restore controlfile to ‘e:\temp\control01.ctl’ from
autobackup;
如果数据库无法Mount,就不能使用如上方式恢复自动备份的控制文件或者参数文件。此时需要我们提供数据库的DBID,才能找到相应的自动备份用以恢复。如果无法得知DBID,那么可以直接指定自动备份集来恢复:
RMAN>restore controlfile to ‘e:\temp\control01.ctl’ from ‘c-2152029224-200905-09
进一步,如果数据库无法nomount,那么恢复spfile文件时会遇到错误,此时可以手工编辑一个pfile文件启动实例,即可以进行spfile恢复,也可以使用RMAN启动默认实例,进行spfile文件恢复,启动默认实例:
RMAN> restore spfile to ‘e:\spfile.ora’ from ‘c-2152029224-200905-09
(4) Resetlogs/noresetlogs与控制文件
控制文件中记录着数据库的数据文件、日志文件、备份数据等信息,更为重要的,控制文件中还记录了数据库的检查点和SCN信息,这些信息在数据库恢复的过程中将起到关键作用。
可以通过如下一条命令将控制文件的创建语句备份到跟踪文件中:
SQL> alter database backup controlfile to trace;
SQL> @gettrcname
当数据库当前的redolog都可用时,可以通过noresetlogs参数重建控制文件,此时oracle能够从日志文件中读取redo信息,记录到控制文件中,由于redo中记录的信息足以重演所有提交成功的事务,所以最终能够实现完全恢复,成功打开数据库,这时的数据库就如同进行了一次断电之后的实例恢复,数据没有损失,重做日志可以继续向前写入。
下面在通过一次测试来看下这个过程:
首先在数据库正常的运行状态,可以执行一次控制文件转储:
SQL>alter session set events ‘immediate trace name controlf
level
这个转储文件中包含数据库的检查点、redo thread信息、数据文件等信息。
接下来通过shutdown abort模拟一个数据库故障:
SQL> shutdown abort;
然后启动数据库到nomount状态,重建控制文件:
SQL> startup nomount;
SQL> create controlfile reuse database “mars” noresetlogs
archivelog;
此时再来转储一次控制文件,检查log file record
经过恢复之后,数据文件达到了一致状态,checkpoint scn和stop scn达到了一致,此时数据库就完成了恢复。
再来看下使用resetlogs的方式重建控制文件:
SQL> create controlfile reuse database “mars” resetlogs
archivelog;
注意到此时控制文件的日志信息都是空的,oracle任务resetlogs方式下,当前的日志文件已经损失,那么就意味着oracle可能丢失提交成功的数据,恢复将是一次不完全的介质恢复。不完全恢复最终要求数据库通过resetlogs方式打开,resetlogs将会强制清空或重建在线日志。此时执行恢复必须使用backup controlfile选项:
SQL> recover database using backup controlfile until cancel;
在完成恢复后需要以resetlogs方式打开数据库:
n
在执行了不完全恢复之后
n
在使用了备份的控制文件进行恢复后
n
使用了带有resetlogs选项创建的控制文件恢复后。
(5) 数据文件头信息与数据库恢复
在数据文件头存在一系列的重要信息,这些信息包括检查点信息、数据库名称、软件版本信息等,在重建控制文件进行恢复时,可以从数据文件头获得这部分信息并写入重建的控制文件用于恢复。那么可以看一下在数据文件头都记录了哪些信息,通过如下命令我们可以将数据文件头信息转储出来:
SQL>alter session set events ‘immediate trace name file_hdrs
level
在输出部分中的checkpointed at scn 和 thread信息,这个两个信息记录了数据文件的检查的SCN和Redo Byte Address(RBA)。这里的RBA包含了重要的恢复信息,代表最后完成的检查点对应的RBA,如果数据文件需要恢复,则需要根据这个RBA来决定应该从哪个日志文件开始。在通过重建控制文件进行恢复时,控制文件中不存在归档日志的相关信息,但是oracle仍然能准确提示我们需要的控制文件名称,那么这个信息从何而来呢?
SQL> recover database using backup controlfile;
这个信息就是来自数据库文件头。
RBA主要由以下三部分组成:
n
日志文件序号
n
日志文件块号
n
日志记录偏移量
具备了这些信息,再加上参数文件中定义的log_archive_format参数,oracle就可以推算出日志序列和日志文件名称,提示恢复。