Oracle 普通数据文件备份与恢复

普通数据文件指:非system表空间、undo_tablespace表空间、临时表空间和只读表空间的数据文件。它们损坏导致用户数据不能访问,不会导致db自身异常、实例崩溃、数据库不恢复就无法启动的情况。

恢复这样的数据文件可以采用高可用策略,在数据库OPEN状态下进行

10.1 普通数据文件损坏的后果

普通数据文件损坏后,只是用户的业务数据不同程度上无法访问(查询与修改),报错

ORA-01578,执行命令的会话不会被中断,即使是数据文件头部损坏检查点发生时实例也不会崩溃

--1 实例启动时,若普通数据文件丢失、无法访问或头部损坏,startup命令只能启动到mount状态。

--2 实例运行时,若普通数据文件头损坏,在发生了检查点之后,由于检查点无法再该数据文件头部完成,此数据文件的状态在控制文件中会被自动设置为off,实例不会崩溃,alert log中有ORA-01171由于检查点失败导致文件下线的错误记录,访问该数据文件ORA-00376错误,实例不再试图访问该文件,此时实例也能重启成功。

--3 实例运行时,若普通数据文件非头部数据块损坏,将导致需要访问受损数据行的命令无法执行,数据文件不会自动下线。

场景1:在启动时发现普通数据文件test01.dbf不存在,数据块只能启动到mount状态

SQL> startup;
Database mounted.
ORA-01157:cannot identify/lock data file 5 -see DBWR trace file
ORA-01110:data file 5 : /u01/app/Oracle/oradata/orcl/test01.dbf

场景2:在启动时发现普通数据文件test01.dbf头部损坏,db只能启动到mount状态

SQL> startup force
Database mounted.
ORA-01122: database file 5 tailed verification check
ORA-01110: data file 5 :  /u01/app/oracle/oradata/orcl/test01.dbf
ORA-01210: data file header is media corrupt

若使用alter database datafile 5 offline,使test01数据文件下线,db还是可以打开的,打开后test01数据文件中的数据都无法访问

SQL> alter database datafile 5 offline;
SQL> alter database open;

--1 损坏的数据文件属于存放历史分区信息的表空间,在线业务不需要或者暂时不需要访问

--2 损坏的数据文件属于一个或几个特定应用的表空间,但是其它相对独立的应用所使用的其他表空间仍然健康,这样做可以使其他应用先提供服务,保证数据库的局部高可用性

场景3:在运行时普通数据文件头损坏,那么在发送检查点时数据文件会被强制下线,在alter log中

ORA-01171: datafile 5 going offline due to error advancing checkpoint
ORA-01122: database file 5 failed verification check
ORA-01110: data file 5 : /u01/app/oracle/oradata/orcl/test01.dbf
ORA-01210: data file header is media corrupt

导致文件内所有业务数据无法访问,比如查询test.t1

SQL> select * from test.t1;
ERROR at line 1:
ORA-00376: file 5 cannot be read at this time
ORA-01110: data file 5 : /u01/app/oracle/oradata/orcl/test01.dbf

若此时重启实例,db也能打开,但5号数据文件依然处于offline,需要手动恢复。

SQL> startup force;
SQL> select * from v$datafile where file#=5;
ERROR at line 1:
ORA-01135: file 5 accessed for DML/query is offline
ORA-01110: data file 5 : /u01/app/oracle/oradata/orcl/test01.dbf

场景4:如果表空间区管理方式是LOCAL,在运行时,数据文件都不区位图(biimap)管理块损坏

SQL> create table t2 (id number) tablespace test;
ORA-01658: unable to create INITIAL extent for segment in tablespace TEST

场景5:实例运行时,表、索引等段头损坏,导致需要读取、修改段头的操作失败

 

SQL> insert into test.t1(id,name) vales (2,’xxx’);
ORA-01578: ORACLE data block corrupted (file # 5,block # 202)
SYS@ orcl >conn yhqt/***
Connected.
YHQT@ orcl >select * from yhqtest_1;
select * from yhqtest_1
              *
ERROR at line 1:
ORA-01578: ORACLE data block corrupted (file # 10, block # 135)
ORA-01110: data file 10: '/u01/app/oracle/oradata/orcl/yhqt01.dbf'

 

场景6: 保存数据的数据块坏块(file # 10, block # 143)

YHQT@ orcl >select * from yhqtest_2;
select * from yhqtest_2
              *
ERROR at line 1:
ORA-01578: ORACLE data block corrupted (file # 10, block # 143)
ORA-01110: data file 10: '/u01/app/oracle/oradata/orcl/yhqt01.dbf'

--更多详细数据块块损坏见DSI系列的物理块损坏和逻辑块损坏

10.2 备份

 

RMAN> backup as compressed backupset tablespace test;
RMAN-00571: ===========================================================
RMAN-00569: =============== ERROR MESSAGE STACK FOLLOWS ===============
RMAN-00571: ===========================================================
RMAN-00558: error encountered while parsing input commands
RMAN-01009: syntax error: found "test": expecting one of: "double-quoted-string, identifier, single-quoted-string"
RMAN-01007: at line 1 column 43 file: standard input
RMAN>  backup as compressed backupset tablespace yhqt;
Starting backup at 18-JUL-19
using channel ORA_DISK_1
channel ORA_DISK_1: starting compressed full datafile backup set
channel ORA_DISK_1: specifying datafile(s) in backup set
input datafile file number=00010 name=/u01/app/oracle/oradata/orcl/yhqt01.dbf
channel ORA_DISK_1: starting piece 1 at 18-JUL-19
RMAN-00571: ===========================================================
RMAN-00569: =============== ERROR MESSAGE STACK FOLLOWS ===============
RMAN-00571: ===========================================================
RMAN-03009: failure of backup command on ORA_DISK_1 channel at 07/18/2019 17:59:04
ORA-19566: exceeded limit of 0 corrupt blocks for file /u01/app/oracle/oradata/orcl/yhqt01.dbf

 

 

SQL> select * from v$database_block_corruption;
    FILE#    BLOCK#      BLOCKS CORRUPTION_CHANGE# CORRUPTIO
---------- ---------- ---------- ------------------ ---------
    10      135          1          0 FRACTURED
    5    2199          1        9533291 CORRUPT
    5    2207          1        9579846 CORRUPT
    5    2231          1        9620379 CORRUPT

 

RMAN> run {
set maxcorrupt for datafile 10 to 135;
backup tablespace yhqt;
}2> 3> 4>
executing command: SET MAX CORRUPT
Starting backup at 18-JUL-19
using channel ORA_DISK_1
channel ORA_DISK_1: starting full datafile backup set
channel ORA_DISK_1: specifying datafile(s) in backup set
input datafile file number=00010 name=/u01/app/oracle/oradata/orcl/yhqt01.dbf
channel ORA_DISK_1: starting piece 1 at 18-JUL-19
channel ORA_DISK_1: finished piece 1 at 18-JUL-19
piece handle=/u01/app/oracle/fra/ORCL/backupset/2019_07_18/o1_mf_nnndf_TAG20190718T180019_gm0jsmbb_.bkp tag=TAG20190718T180019 comment=NONE
channel ORA_DISK_1: backup set complete, elapsed time: 00:00:01
Finished backup at 18-JUL-19
Starting Control File and SPFILE Autobackup at 18-JUL-19
piece handle=/u01/app/oracle/fra/ORCL/autobackup/2019_07_18/o1_mf_s_1013968820_gm0jsndn_.bkp comment=NONE
Finished Control File and SPFILE Autobackup at 18-JUL-19

备份SYSAUX表空间为镜像复制

RMAN> backup as copy tablespace sysaux;
Starting backup at 18-JUL-19
using channel ORA_DISK_1
channel ORA_DISK_1: starting datafile copy
input datafile file number=00002 name=/u01/app/oracle/oradata/orcl/sysaux01.dbf
output file name=/u01/app/oracle/fra/ORCL/datafile/o1_mf_sysaux_gm0jwl05_.dbf tag=TAG20190718T180153 RECID=2 STAMP=1013968917
channel ORA_DISK_1: datafile copy complete, elapsed time: 00:00:07
Finished backup at 18-JUL-19
Starting Control File and SPFILE Autobackup at 18-JUL-19
piece handle=/u01/app/oracle/fra/ORCL/autobackup/2019_07_18/o1_mf_s_1013968921_gm0jws37_.bkp comment=NONE
Finished Control File and SPFILE Autobackup at 18-JUL-19

运行以上命令RMAN命令时,先确保数据库在mount状态或者open状态,open状态下还需要开启归档日志模式。

10.3 恢复

普通数据文件的恢复的核心步骤:是该数据文件下线、从备份还原(restore或switch)使用增量备份或重做日志恢复(recover命令),最后再令文件上线

普通数据文件恢复的主要特点是既可以在数据库mount状态下恢复(过程中db不可用),也可以保持db在open状态下恢复(db局部可用)。数据文件头部损坏的情况可能需要特殊处理。

10.3.1 恢复前的准备

与关键数据文件的恢复一样,进入mount状态时恢复的前提,确保参数文件和控制文件正常。

若关键数据文件(system,undo)有损坏,首先应该恢复关键数据文件。

这一篇讨论的内容建立在参数文件、控制文件、关键数据文件正常的情况下。

若在open状态下对普通数据文件进行修复,首先必须确保被恢复的文件已处于offline状态。

10.3.2 非文件头部损坏后的恢复

只要文件头部没有损坏(包括文件丢失),文件就不会被自动下线,也不会出现ORA-01210错误,可以使用此节的步骤进行恢复,数据库处于mount状态为低可用恢复策略,数据库处于open状态为高可用恢复策略。

--1 使用shutdown abort关闭实例

--2 执行startup mount启动到mount状态

--3 RMAN执行restore(或switch) 还原损坏的普通数据文件

--4 通过RMAN执行recover database 利用归档日志和在线重做日志恢复数据文件

--5 alter database open 打开数据库


以yhqt01.dbf数据文件为例

--mount状态恢复

RMAN> run {
shutdown abort;
startup mount;
restore datafile '/u01/app/oracle/oradata/orcl/yhqt01.dbf';
recover database;
alter database open;}

--open状态恢复,实例未关闭

RMAN> run {
sql'alter database datafile 10 offline';
restore datafile 10;
recover datafile 10;
sql'alter database datafile 10 online';
}

--open状态, 实例已关闭

 

RMAN> run {
startup mount;
sql'alter database datafile 10 offline';
alter database open;
restore datafile 10;
recover datafile 10;
sql'alter database datafile 10 online';
}

 

10.3.3 文件头部损坏后的恢复

数据文件头部损坏之后,如果又处于offline状态,将来执行restore命令时通道会“不认识”这种文件,导致还原无法完成。Alert log中出现ORA-01210

场景:yhqt01.dbf文件头部已经损坏,随后检查点也已发生,告警日志中出现ORA-01210和ORA-01171错误,并已在控制文件中将yhqt01.dbf文件的状态修改为offline,

用户访问yhqt表空间的对象都返回ORA-00376: file 10 cannot be read at this time

此时用restore命令还原yhqt01.dbf文件将意外引发RMAN-06010错误,原因是控制文件表示该文件已下线,restore发现yhqt01.dbf存在,通道还是会访问yhqt01.dbf文件头部,

以确认其信息是否与控制文件中的一致,但损坏的是文件头,命令失败。

解决:

--1 删除头部已损坏的数据文件,这样通道就不会尝试检查文件头,当做文件丢失处理

--2 在db处于mount状态用alter database datafile ... online将数据文件修改为online,再使用restore

RMAN> restore datafile 10;
ORA-01135: file 10 accessed for DM/query is offline
ORA-01110: datafile 10 :/u01/app/oracle/oradata/orcl/yhqt01.dbf
RMAN-06010: error while looking up datafile 10
删除该数据文件
$ rm /u01/app/oracle/oradata/orcl/yhqt01.dbf
RMAN> restore datafile 10;
RMAN> recover datafile 10;
SQL> alter database open;
SQL> alter database datafile 10 online;

所以数据文件头部损坏后的修复步骤应该在低可用策略与高可用策略的基础上,再根据相关数据文件是否已经offline区分,总共3种:

--1未下线低可用策略恢复(online,mount)

--2已下线低可用策略恢复(offline,mount)

--3已下线高可用策略恢复(offline,open)

1的恢复的主要步骤

--1 使用shutdown abort关闭实例
--2 执行startup mount启动实例到mount状态
--3 RMAN执行restore或switch还原损坏的普通数据文件
--4 RMAN执行recover database 利用归档日志和在线日志恢复数据文件
--5 alter database open 打开数据库,恢复完成
RMAN> run {
shutdown abort;
startup mount;
restore datafile 10;
recover database;
alter database open;}

2的恢复主要步骤

--1 使用shutdown abort关闭实例
--2 startup mount到mount状态
--3 alter databse datafile 10 online将数据文件在控制文件中的状态修改为上线
--4 RMAN> restore datafile 10; 还原数据文件
--5 RMAN> recover database;
--6 SQL>alter database open;
RMAN> run {
shutdown abort;
startup mount;
sql'alter database 10 online';
restore datafile 10;
recover database;
alter database open;}

3的恢复主要步骤

--1 使用操作命令删除损坏的头部的普通数据文件,若非头部损坏忽略此步骤
--2 如果实例已经停止,startup mount启动到mount状态,如果数据库open状态,则忽略此步骤
--3 alter database 10 offline;
--4 如果符合第二步的条件,使用alter database open 打开数据库,否则忽略此步骤
--5 使用RMAN> restore datafile 10;
--6 RMAN>recover tablespace或者recover datafile,利用归档和redo log恢复数据文件
--7 执行alter database datafile 10 online;
$ rm /u01/app/oracle/oradata/orcl/yhqt01.dbf
--实例未关闭
RMAN> run {
sql'alter database datafile 10 offline';
restore datafile 10;
recover datafile 10;
sql'alter database datafile 10 online';
}
--实例已关闭
RMAN> run {
startup mount;
sql'alter database datafile 10 offline';
alter database open;
restore datafile 10;
recover datafile 10;
sql'alter database datafile 10 online';
}