坏块的发生,很罕见,但生产系统偶尔还是会出现。如果有物理备份,处理起来相对简单,直接进行块级recover即可,但如果只有逻辑备份呢?处理起来要分四种情况,在此总结一下:
一、datafile的数据块坏了,在sql执行扫描到这个块的时候会报ORA-01578:
ERROR at line 1:
ORA-01578: ORACLE data block corrupted (file # 21, block # 12)
ORA-01110: data file 21: '/u01/app/oracle/oradata/RWDB_production/T6.DBF'
但是,这种坏块不会影响数据库重启,只是在重启到open阶段的时候会报:
Thu Nov 20 10:39:00 CST 2014
Corrupt Block Found
TSN = 26, TSNAME = CORRUPT
RFN = 21, BLK = 12, RDBA = 88080396
OBJN = 591083, OBJD = 591083, OBJECT = USER_TAB, SUBOBJECT =
SEGMENT OWNER = RWUSER, SEGMENT TYPE = Table Segment
db在open的时候会扫描数据文件的状态,这里可以清楚地看到是什么类型的段、什么用户、什么对象出现了坏块。还可以用dbv工具进一步check:
[oracle@BJ-TEST]/u01/app/oracle/admin/RWDB>dbv file=/u01/app/oracle/oradata/RWDB_production/T6.DBF
DBVERIFY - Verification complete
Total Pages Examined : 25
Total Pages Processed (Data) : 0
Total Pages Failing (Data) : 0
Total Pages Processed (Index): 0
Total Pages Failing (Index): 0
Total Pages Processed (Other): 11
Total Pages Processed (Seg) : 0
Total Pages Failing (Seg) : 0
Total Pages Empty : 13
Total Pages Marked Corrupt : 1
Total Pages Influx : 0
Highest block SCN : 1132783081 (0.1132783081)
这里也可以看到Total Pages Marked Corrupt为1,即有1个坏块。
处理:
这种类型的坏块,处理办法有很多,support上的建议办法如下:
1、用DBMS_REPAIR.SKIP_CORRUPT_BLOCKS处理,即跳过坏块。
2、用CTAS建一个临时表,上面坏了的表为user_tab,可建一个临时表user_tab_tmp
3、将user_tab表重命名:alter table user_tab rename to user_tab_corrupt
4、将user_tab_tmp改为生产系统正式表:alter table user_tab_tmp rename to user_tab
5、重建user_tab表的索引
这种恢复办法,那个坏块里面的数据会丢掉。如果是每天都进行逻辑备份,还可以将现在的user_tab与昨天逻辑备份里面的user_tab进行比对,以最大限度恢复数据。
二、datafile的head块坏了(1号块)
一个8k block大小的数据文件,我们用ultraedit打开,以16进制方式显示,其中00000000~00001ff0是0号块,后面开始是1号块,即这个数据文件的head块。这个块坏了就相当危险,数据库重启会直接报错:
SQL> conn /as sysdba;
Connected to an idle instance.
SQL> startup;
ORACLE instance started.
Total System Global Area 935329792 bytes
Fixed Size 2100680 bytes
Variable Size 385876536 bytes
Database Buffers 541065216 bytes
Redo Buffers 6287360 bytes
Database mounted.
ORA-01122: database file 24 failed verification check
ORA-01110: data file 24: '/u01/app/oracle/oradata/RWDB_production/T9.DBF'
ORA-01210: data file header is media corrupt
可以看到,数据库打不开了。
alert报下面的东西:
Thu Nov 20 15:11:10 CST 2014
ALTER DATABASE OPEN
Read of rdba: 0x06000001 (file 24, block 1) failed with ORA-01210.
Hex dump of (file 24, block 1) in trace file /u01/app/oracle/admin/RWDB/udump/rwdb_ora_5850.trc
Corrupt block relative dba: 0x06000001 (file 24, block 1)
Bad header found during datafile header read
Data in bad block:
type: 49 format: 1 rdba: 0x31000031
last change scn: 0x0000.00000000 seq: 0x31 flg: 0x31
spare1: 0x0 spare2: 0x0 spare3: 0x0
consistency value in tail: 0x00000b01
check value in block header: 0x3131
block checksum disabled
Trying reread from disk.
Reread of rdba: 0x06000001 (file 24, block 1) failed with ORA-01210
ORA-1122 signalled during: ALTER DATABASE OPEN...
dbv也可以检测到:
[oracle@BJ-TEST]/u01/app/oracle/admin/RWDB/bdump>dbv file=/u01/app/oracle/oradata/RWDB_production/T9.DBF
DBVERIFY - Verification complete
Total Pages Examined : 25
Total Pages Processed (Data) : 1
Total Pages Failing (Data) : 0
Total Pages Processed (Index): 0
Total Pages Failing (Index): 0
Total Pages Processed (Other): 10
Total Pages Processed (Seg) : 0
Total Pages Failing (Seg) : 0
Total Pages Empty : 13
Total Pages Marked Corrupt : 1
Total Pages Influx : 0
Highest block SCN : 1132794574 (0.1132794574)
如果半夜干升级割接(要重启服务器),遇到这种问题,身边又没有DBA,还是很棘手的,业务直接就会中断,如果是HA的系统,坏的datafile又刚好在磁阵上,那么通过切换也无法解决这个问题,因为oracle资源组就起不来。对于非归档模式的数据库,解决方法如下:
SQL> ALTER DATABASE DATAFILE '/u01/app/oracle/oradata/RWDB_production/T9.DBF' OFFLINE DROP;
Database altered.
SQL> alter database open;
Database altered.
这里,先不管数据丢失与否,先启动了数据库再说,免得故障闹大!:)
三、datafile的os head块坏了(0号块)
什么是datafile的0号块?官方称之为操作系统的头块,里面的东西不是oracle写的,是操作系统记录的文件大小等文件系统相关的信息。0号块坏了,可以正常重启数据库,没问题。但是,如果哪一天遇到紧急问题需要重建控制文件,将会面临报错:
ORA-27047: unable to read the header block of file
对于0号块的检测,用前面的dbv根本检测不出来(dbv命令貌似不检测0号块),需要用dbfsize来检测:
[oracle@BJ-TEST]/u02/backup>dbfsize /u01/app/oracle/oradata/RWDB_production/T8.DBF
/u01/app/oracle/oradata/RWDB_production/T8.DBF: Header block magic number is bad
这里会提示一个什么magic号坏了。
解决方法:
resize一下有问题的数据文件大小,os block head就会被重写,问题可以解决。
alter database datafile '/u01/app/oracle/oradata/RWDB_production/T8.DBF' resize
四、整个datafile都坏了(各种坏块的综合体)
笔者曾遇到过一次,整个文件都坏了,这种问题,可看做是以上坏块情况的集体爆发。
如:
dbvfile=/data1/app/oracle/oradata/RWDB/IRDBRoamerTS_01.dbf
Total Pages Examined : 1926
Total Pages Processed (Data) : 0
Total Pages Failing (Data) : 0
Total Pages Processed (Index): 0
Total Pages Failing (Index): 0
Total Pages Processed (Other): 0
Total Pages Processed (Seg) : 0
Total Pages Failing (Seg) : 0
Total Pages Empty : 0
Total Pages Marked Corrupt : 1926
Total Pages Influx : 0
Highest block SCN : 0 (0.0)
这里可以看到,总共检测了1926个块,全坏了。如果遇到数据库重启,就无法open成功。
如果有RMAN备份,这种情况就很简单,直接restore、recover坏的数据文件就行。如果没有物理备份,就要先用上面第二种情况的解决办法先把数据库打开,然后再恢复数据。恢复数据的方法,与第二种里面又有所不同,既然这个文件里的块都坏了,再skip哪个块就没意义了。恢复数据的步骤如下:
1、看看这个dbf里面有哪些对象
2、用最新的逻辑备份将上面的对象impdp进新的表空间(如果IRDBRoamerTS_01不是表空间下的唯一文件,也可以不用建新的表空间)