4.1 不完全恢复的特点: 1)让整个database 回到过去某个时间点,不能避免数据丢失。 2)想跳过坏日志而继续恢复所有其他工作是不可能的,前滚没有这个功能(注意点)。 3)必须以sysdba身份连接进行不完全恢复,普通用户或sysoper都不行(注意点)。 4)语句只有recover database until 这种形式,表示整个数据库回到某个时间点或SCN,而until是指恢复在时间点前停止(注意点)。 4.2 不完全恢复(Incomplete recover) 适用环境: 1)在过去的某个时间点重要的数据被破坏。 2)在做完全恢复时,丢失了归档日志或当前online redo log(注意点) 3)当误删除了表空间时(有控制文件备份) 4)丢失了所有的控制文件,使用备份的控制文件恢复时 (条件满足时可以完全恢复) 4.3 不完全恢复的基本类型: 1)基于时间点 (until time):使整个数据库恢复到过去的一个时间点前 2)基于scn (until change):使整个数据库恢复到过去的某个SCN前 3)基于cancel (until cancel):使整个数据库恢复到归档日志或当前日志的断点前 4)基于误删除表空间(使用备份的controlfile):使整个数据库恢复到误删除表空间前 4.4、logminer 工具的使用 对redo log 进行挖掘,找出在某个时间点所作的DDL 或DML 误操作(包括:时间点、scn 、sql语句) 4.5 不完全恢复范例: 范例1: 恢复过去某个时间点误删除的table 4.5.1 基于时间点的不完全恢复 1)环境:scott用户在test表空间下有个t1表 sql> conn scott/scott sql> select * from t1; ID ---------- 1 2 2)误删除了t1表,并purge了。 sql> drop table t1 purge; sql> select * from v$log; GROUP# THREAD# SEQUENCE# BYTES MEMBERS ARCHIVED STATUS FIRST_CHANGE# FIRST_TIME ---------- ---------- ---------- ---------- ---------- -------- ---------------- ------------- ----------- 1 1 131 52428800 1 YES INACTIVE 1875893 2012-6-13 1 2 1 132 52428800 1YES INACTIVE 1896385 2012-6-13 1 3 1 133 52428800 1 NO CURRENT 1916973 2012-7-18 1 sql> alter system switch logfile; sql> / sql> / sql> select name from v$archived_log; NAME -------------------------------------------------------------------------------- ... /u01/disk1/timran/arch_1_782662700_129.log /u01/disk1/timran/arch_1_782662700_130.log /u01/disk1/timran/arch_1_782662700_131.log /u01/disk1/timran/arch_1_782662700_132.log /u01/disk1/timran/arch_1_782662700_133.log//drop table t1 purge这个动作的日志条目记录在此归档日志里了。 /u01/disk1/timran/arch_1_782662700_134.log /u01/disk1/timran/arch_1_782662700_135.log 116 rows selected 3)通过logmr 找出误操作的ddl命令的timestamp 或 san sql> show parameter utl NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ create_stored_outlines string utl_file_dir string /home/oracle/logmnr sql> execute dbms_logmnr_d.build('dict.ora','/home/oracle/logmnr',dbms_logmnr_d.store_in_flat_file); sql> execute dbms_logmnr.add_logfile(logfilename=>'/u01/disk1/timran/arch_1_782662700_133.log',options=>dbms_logmnr.new); sql> execute dbms_logmnr.add_logfile(logfilename=>'/u01/disk1/timran/arch_1_782662700_134.log',options=>dbms_logmnr.addfile); sql> execute dbms_logmnr.start_logmnr(dictfilename=>'/home/oracle/logmnr/dict.ora',options=>dbms_logmnr.ddl_dict_tracking); sql> select username,scn,to_char(timestamp,'yyyy-mm-dd hh24:mi:ss'),sql_redo from v$logmnr_contents WHERE lower(sql_redo) like 'drop table%'; USERNAME SCN TO_CHAR(TIMESTAMP,'YYYY-MM-DDH sql_REDO ------------------------------ ---------- ------------------------------ ----------------------------------------------- SCOTT 1918000 2012-08-01 17:28:29 drop table t1 purge; sql> execute dbms_logmnr.end_logmnr; 4) 关闭数据库,删除所有dbf,准备做不完全恢复 sql> alter system checkpoint; //控制文件更新 sql> shutdown abort [oracle@timran ~]$ cd /u01/oradata/timran11g [oracle@timran ~]$ rm *.dbf 5)还原所有备份的数据文件 [oracle@timran ~]$ cp /u01/back1/*.dbf ./ 6)根据log miner提供的信息,做基于时间点的不完全恢复 17:31:43 sql> startup 17:33:07 sql> recover database until time '2012-08-01 17:28:29'; ORA-00279: change 1917581 generated at 07/18/2012 16:46:34 needed for thread 1 ORA-00289: suggestion : /u01/disk1/timran/arch_1_782662700_133.log ORA-00280: change 1917581 for thread 1 is in sequence #133 17:33:17 Specify log: {<RET>=suggested | filename | AUTO | CANCEL} auto Log applied. Media recovery complete. 7)resetlogs方式打开数据库 sql> alter database open resetlogs; 8)验证 sql> select * from scott.t1; ID ---------- 1 2 9)看看在resetlogs后,日志sequence重置了。 sql> select * from v$log; GROUP# THREAD# SEQUENCE# BYTES MEMBERSARCHIVED STATUS FIRST_CHANGE# FIRST_TIME ---------- ---------- ---------- ---------- ---------- -------- ---------------- ------------- ---------------------------------------------------------------------- 1 1 0 52428800 1 YES UNUSED 0 2 1 0 52428800 1 YES UNUSED 0 3 1 1 52428800 1 NO CURRENT 1918000 2012-8-1 17 4.5.2 基于SCN的不完全恢复(略) 在手工基于scn的不完全恢复的命令子句是change关键字,与基于时间的不完全恢复类似,其命令格式只要将recover命令换成下面即可: sql> recover database until change 1918000; 这里不多赘述了。 4.5.3 基于cancel的不完全恢复(略) 4.5.4 基于backup controlfile 的恢复 不完全恢复中的复杂性是恢复数据文件的时候使用备份的控制文件。 1)为什么会使用备份的控制文件? 实际工作中主要有两种情况: 第一种:当前控制文件全部损坏,而数据文件备份,控制文件备份及当前日志处于不同SCN版本,它们之间又增加过表空间(数据文件)。 第二种:当前控制文件没有损坏,但想要恢复被删除的表空间。 2)使用备份的控制文件恢复数据库的语法: recover database until [time|change] using backup controlfile; 注意:[time|change]是可选的,就是说如果条件满足,仍然可以做到完全恢复。 然后会有如下选项: Specify log: {<RET>=suggested | filename | AUTO | CANCEL} 此语法的出现是由于控制文件和当前日志中不一致,当前日志的scn总是最新的,而控制文件可能是老的或尚未更新的(shutdwon abort过)。 AUTO:自动使用archivelog前滚恢复,但一般不包括前滚current log; filename: 输入当前文件的路径和文件名,是指current log的恢复 CANCEL: 退出。 注意点: 1)在控制文件丢失后进行恢复将会将会出现停机时间,因此不能联机执行控制文件的恢复。 2)使用backup controlfile子句的恢复数据库之后,一律要使用alter database open resetlogs打开数据库。 范例1:(属于第一种情况) 环境:当前控制文件损坏,数据文件损坏,有全备但之后增加了表空间,并备份了配套的控制文件。 模式:所有数据文件备份(老)------(新建表空间abcd)-----备份控制文件(次新)------日志文件(新) 分析:新建表空间数据文件损坏,全备里没有该数据文件的备份及控制文件描述,当前控制文件又丢失,只能用备份的控制文件恢复。 1)环境: sql> select * from v$tablespace; TS# NAME INC BIG FLA ENC ---------- ------------------------------ --- --- --- --- 0 SYSTEM YES NO YES 1 SYSAUX YES NO YES 4 USERS YES NO YES 6 EXAMPLE YES NO YES 8 TEST YES NO YES 2 UNDOTBS1 YES NO YES 3 TEMP NO NO YES sql> select * from v$log; GROUP# THREAD# SEQUENCE# BYTES MEMBERS ARC STATUS FIRST_CHANGE# FIRST_TIME ---------- ---------- ---------- ---------- ---------- --- ---------------- ------------- -------------------------------------------------------------- 1 1 7 52428800 1 NO CURRENT 6676574 2013-01-17 13:55:19 2 1 5 52428800 1 YESINACTIVE 6676549 2013-01-17 13:54:14 3 1 6 52428800 1 YES INACTIVE 6676562 2013-01-17 13:54:48 sql> create tablespace abcd datafile '/u01/oradata/timran11g/abcd01.dbf' size 5m; sql> create table scott.a1 (name char(10)) tablespace abcd; sql> insert into scott.a1 values('a'); sql> commit; sql> select * from scott.a1; NAME ---------- a sql> alter system switch logfile; 2)备份控制文件 19:17:55 sql> alter database backup controlfile to '/u01/oradata/timran11g/con.bak1'; 3) 模拟abcd01.dbf损坏,查证访问数据文件报错。 [oracle@timran ~]$rm /u01/oradata/timran11g/abcd01.dbf//数据库open状态,删除abcd01.dbf数据文件 sql> alter system flush buffer_cache;//db buffer 清空 sql> conn / as sysdba//换个session查看 a1表物理读失败 sql> select * from scott.a1; 4)关闭数据库 sql> shutdown abort; 5)恢复所有数据文件备份,准备做不完全恢复 [oracle@timran timran11g]$ cd /u01/oradata/timran11g [oracle@timran timran11g]$ rm *.ctl [oracle@timran timran11g]$ rm *.dbf [oracle@timran timran11g]$ cp /u01/back1/*.dbf ./ [oracle@timran timran11g]$ cp con.bak1 control01.ctl [oracle@timran timran11g]$ cp con.bak1 control02.ctl [oracle@timran timran11g]$ cp con.bak1 control03.ctl sql> startup sql> col name for a50; sql> select file#,checkpoint_change#,name from v$datafile; FILE# CHECKPOINT_CHANGE# NAME ---------- ------------------ -------------------------------------------------- 1 6676574 /u01/oradata/timran11g/system01.dbf 2 6676574 /u01/oradata/timran11g/sysaux01.dbf 3 6676601 /u01/oradata/timran11g/abcd01.dbf 4 6676574 /u01/oradata/timran11g/user01.dbf 5 6676574 /u01/oradata/timran11g/example01.dbf 6 6676574 /u01/oradata/timran11g/test01.dbf 7 6676574 /u01/oradata/timran11g/undotbs01.dbf sql> select file#,checkpoint_change# from v$datafile_header; FILE# CHECKPOINT_CHANGE# ---------- ------------------ 1 6676343 2 6676343 3 0 4 6676343 5 6676343 6 6676343 7 6676343 //可以看出:1)file3 在控制文件里记录是abcd01.dbf,而与之对应的数据文件3是不存在的,2)备份的数据备份的scn比控制文件scn还老。 6)使用备份控制文件恢复 sql> recover database using backup controlfile; ORA-00283: 恢复会话因错误而取消 ORA-01110: 数据文件 3: '/u01/oradata/timran11g/abcd01.dbf' ORA-01157: 无法标识/锁定数据文件 3 - 请参阅 DBWR 跟踪文件 ORA-01110: 数据文件 3: '/u01/oradata/timran11g/abcd01.dbf' //此错是因为老备份里没有abcd表空间,但只要控制文件里记录了abcd就好办,方法是建一个datafile的空文件,而其中内容可由日志文件recover(前滚)时填补出来。 sql> alter database create datafile '/u01/oradata/timran11g/abcd01.dbf'; ---再次使用备份控制文件恢复 sql> recover database using backup controlfile; ...... ORA-00308: 无法打开归档日志 '/u01/disk1/timran/arch_1_804846837_9.log' ORA-27037: 无法获得文件状态 Linux Error: 2: No such file or directory Additional information: 3 //archive日志前滚结束了,但当前日志里还有信息需要恢复 //注意: 对于这个例子来说,一定要看清提示:如果提示的不是归档的日志(是当前日志),则要直接要输入filename 不能输入auto,否则open时会失败。 sql> recover database using backup controlfile; //再次做恢复 指定日志: {<RET>=suggested | filename | AUTO | CANCEL} /u01/oradata/timran11g/redo03.log//把蛇头(当前日志)给它。 已应用的日志。 完成介质恢复。 7)resetlogs打开数据库 sql> alter database open resetlogs; 8)验证 sql> select * from scott.a1; NAME ---------------------------------------- a 范例2:(属于第一种情况)(略) 环境:当前控制文件损坏,新建表空间在备份控制文件之后 模式:全备(老)-----备份控制文件(次新)-----新建表空间timran------日志文件(新) 分析:整个恢复过程中datafile结构有了变化,变化发生在备份控制文件之后,新增了表空间timran,控制文件备份里没有此表空间记录,但日志里有。 1)环境 sql> drop tablespace abcd including contents and datafiles; sql> alter database backup controlfile to '/u01/oradata/timran11g/con.bak2'; sql> create tablespace timran datafile '/u01/oradata/timran11g/timran01.dbf' size 5m; sql> create table scott.r1 (id int) tablespace timran ; sql> insert into scott.r1 values(1); sql> commit; sql> select * from v$tablespace; TS# NAME INC BIG FLA ENC ---------- -------------------------------------------------- --- --- --- --- 0 SYSTEM YES NO YES 1 SYSAUX YES NO YES 14 TIMRAN YES NO YES 4 USERS YES NO YES 6 EXAMPLE YES NO YES 8 TEST YES NO YES 3 TEMP NO NO YES 2 UNDOTBS1 YES NO YES sql> select * from scott.r1; ID ---------- 1 sql> select * from v$log; GROUP# THREAD# SEQUENCE# BYTES MEMBERS ARC STATUS FIRST_CHANGE# FIRST_TIME ---------- ---------- ---------- ---------- ---------- --- ---------------- ------------- ----------------------------------------------------------------- 1 1 1 52428800 1 NO CURRENT 6677119 2013-01-17 14:08:18 2 1 0 52428800 1 YES UNUSED 0 3 1 0 52428800 1 YES UNUSED 0 2)模拟新建数据文件损坏,查证访问数据文件报错。 [oracle@timran timran11g]rm timran01.dbf sql>alter system flush buffer_cache; sql>conn / as sysdba sql>select * from scott.r1; 3) 关闭数据库 sql>shutdown abort 4)还原所有数据文件,以老控制文件替换当前控制文件 [oracle@timran timran11g]$ cd /u01/oradata/timran11g [oracle@timran timran11g]$ rm *.ctl [oracle@timran timran11g]$ rm *.dbf [oracle@timran timran11g]$ cp /u01/back1/*.dbf ./ [oracle@timran timran11g]$ cp con.bak2 control01.ctl [oracle@timran timran11g]$ cp con.bak2 control02.ctl [oracle@timran timran11g]$ cp con.bak2 control03.ctl 5)启动数据库 sql> startup ORACLE 例程已经启动。 ...... 数据库装载完毕。 ORA-01589: 要打开数据库则必须使用 RESETLOGS 或 NORESETLOGS 选项 sql> select file#,name from v$datafile; FILE# CHECKPOINT_CHANGE# NAME ---------- ------------------ -------------------------------------------------- 1 6677122 /u01/oradata/timran11g/system01.dbf 2 6677122 /u01/oradata/timran11g/sysaux01.dbf 4 6677122 /u01/oradata/timran11g/user01.dbf 5 6677122 /u01/oradata/timran11g/example01.dbf 6 6677122 /u01/oradata/timran11g/test01.dbf 7 6677122 /u01/oradata/timran11g/undotbs01.dbf sql> select file#,checkpoint_change# from v$datafile_header; FILE# CHECKPOINT_CHANGE# ---------- ------------------ 1 6676343 2 6676343 4 6676343 5 6676343 6 6676343 7 6676343 6)使用备份控制文件恢复数据库 sql> recover database using backup controlfile; ORA-00279: 更改 6676343 (在 01/16/2013 14:11:39 生成) 对于线程 1 是必需的 ORA-00289: 建议: /u01/disk1/timran/arch_1_804846837_4.log ORA-00280: 更改 6676343 (用于线程 1) 在序列 #4 中 指定日志: {<RET>=suggested | filename | AUTO | CANCEL} auto ...... 指定日志: {<RET>=suggested | filename | AUTO | CANCEL} /u01/oradata/timran11g/redo01.log ...... ORA-00283: 恢复会话因错误而取消 ORA-01244: 未命名的数据文件由介质恢复添加至控制文件 ORA-01110: 数据文件 3: '/u01/oradata/timran11g/timran01.dbf' ORA-01112: 未启动介质恢复 sql> select file#,name from v$datafile; FILE# CHECKPOINT_CHANGE# NAME ---------- ------------------ -------------------------------------------------- 1 6678002 /u01/oradata/timran11g/system01.dbf 2 6678002 /u01/oradata/timran11g/sysaux01.dbf 3 6677999 /u01/oracle/dbs/UNNAMED00003//注意这个问题,老控制文件不知道之后的timran01.dbf 4 6678002 /u01/oradata/timran11g/user01.dbf 5 6678002 /u01/oradata/timran11g/example01.dbf 6 6678002 /u01/oradata/timran11g/test01.dbf 7 6678002 /u01/oradata/timran11g/undotbs01.dbf sql> select file#,checkpoint_change# from v$datafile_header; FILE# CHECKPOINT_CHANGE# ---------- ------------------ 1 6678002 2 6678002 3 0 4 6678002 5 6678002 6 6678002 7 6678002 7)重命名数据文件 sql> alter database create datafile '/u01/oracle/dbs/UNNAMED00003' as '/u01/oradata/timran11g/timran01.dbf'; //上面的命令一石二鸟,自动完成了两个动作1)加了一个数据文件timran01.dbf,2)重命名控制文件UNNAMED00003为timran01.dbf sql> select file#,name from v$datafile; FILE# CHECKPOINT_CHANGE# NAME ---------- ------------------ -------------------------------------------------- 1 6678002 /u01/oradata/timran11g/system01.dbf 2 6678002 /u01/oradata/timran11g/sysaux01.dbf 3 6677999 /u01/oradata/timran11g/timran01.dbf 4 6678002 /u01/oradata/timran11g/user01.dbf 5 6678002 /u01/oradata/timran11g/example01.dbf 6 6678002 /u01/oradata/timran11g/test01.dbf 7 6678002 /u01/oradata/timran11g/undotbs01.dbf sql> recover database using backup controlfile; 8)resetlogs打开数据库 sql> alter database open resetlogs; 9)验证 sql> select * from scott.r1; ID ---------- 1 范例3 恢复被删除的表空间(属于第二种情况)(略去,将在RMAN中介绍) 环境:用户使用正常操作命令删除了表空间及其数据文件,但之后又希望恢复删除的表空间。全备里有这个表空间的数据文件。 模式:全备(老)------控制文件备份(次新)-----删除表空间------所需日志(新) 分析:当用户使用drop tablesapce xxx including contents and datafiles 这条DDL语句后,数据库的结构发生了变更,涉及了三个地方。 a)控制文件 b)该表空间下的数据文件 c)系统表空间(数据字典) 特别提醒的是:当前的控制文件里已经没有该表空间的信息了,所以不能使用当前的控制文件做恢复。恢复这个表空间要满足三个条件: a)要有该表空间的数据文件备份 b)使用不完全恢复(基于时间点或scn) c)使用备份的控制文件,而这个控制文件是删除该表空间前的控制文件,不是当前的控制文件。这个非常重要,该控制文件中的内容记录了你需要恢复数据库结构,重要的这个控制文件必须 包括有你要恢复的那个表空间的信息。 1)背景: sql> select * from v$tablespace; TS# NAME INC BIG FLA ENC ---------- ------------------------------ --- --- --- --- 0 SYSTEM YES NO YES 1 SYSAUX YES NO YES 5 UNDOTBS2 YES NO YES 4 USERS YES NO YES 6 EXAMPLE YES NO YES 8 TEST YES NO YES 3 TEMP NO NO YES sql> create table scott.t1(id int) tablespace test; sql> insert into scott.t1 values(1); sql> commit; sql> alter system switch logfile; sql> / sql> / 2)记录下当前scn sql> select current_scn from v$database; CURRENT_SCN ----------- 7222848 3)备份控制文件 sql> alter database backup controlfile to '/u01/oradata/timran11g/con.bak' 4)删除表空间及数据文件 sql> drop tablespace test including contents and datafiles; sql> shutdown abort 5)删除所有数据文件和当前控制文件,还原所有数据文件及备份的控制文件 [oracle@timran timran11g]$ rm *.dbf [oracle@timran timran11g]$ rm *.ctl [oracle@timran timran11g]$ cp /u01/back1/*.dbf ./ [oracle@timran timran11g]$ cp con.bak control01.ctl [oracle@timran timran11g]$ cp con.bak control02.ctl [oracle@timran timran11g]$ cp con.bak control03.ctl 6)启动数据库后,要做基于时间点(或SCN)的不完全恢复 sql> startup ... 数据库装载完毕。 ORA-01589: 要打开数据库则必须使用 RESETLOGS 或 NORESETLOGS 选 sql> recover database until change 7222848 using backup controlfile; 7)以不完全恢复方式打开数据库 sql> alter database open resetlogs; 8)验证 sql> select * from scott.t1; ID ---------- 1