Oracle数据块恢复(dbv、BMR)
物理坏块和逻辑坏块
Oracle数据文件的坏块可以分为物理坏块和逻辑坏块。物理坏块指的是块格式本身已经损坏,块内的数据没有任何意义。而逻辑坏块,指的是块内的数据在逻辑上存在问题,比如说索引块的索引值没有按从小到大排列导致的逻辑坏块。物理坏块一般是由于内存问题、OS问题、I/O子系统问题或硬件引起的,逻辑坏块一般是有Oracle bug等原因引起的。
各种各样的块损坏通常是通过Oracle的ORA-1578错误报告出来的,详细的损坏描述会在告警日志中打印出来。
l 物理块损坏
块的物理损坏有很多种情况,例如块头(Cache Header)被一个不正确的值替换、块被破坏或变得不完整、块的头和尾不匹配、块的校验和(CHECKSUM)不正确、块错位、块被归零。
n 破裂块
一个破裂块的意思即块是不完整的,块头的信息不能匹配块尾的信息。在告警日志中可能出现如下的日志信息:
Corrupt block relative dba:0x0380e573(file 14,block 58739)
Fractured block found during buffer read
……
n 不正确的校验和
块的校验和也是数据块的一致性检查的依据。块的一致性检查由DB_BLOCK_CHECKSUM和DB_BLOCK_CHECKING两个初始化参数控制。DB_BLOCK_CHECKSUM是一种物理检查,DB_CHECK_CHECKING是一种逻辑检查。
参数1 DB_CHECK_CHECKSUM
DB_BLOCK_CHECKSUM只有在写入(DBWn常规写或用户进程直接路径写入)时,根据一个CHECKSUM算法计算数据块的校验和,然后写入数据块的一个特定位置(CACHE HEADER,具体是以0字节算起,块的第16~17字节),在读取块时再进行检验。主要是防止I/O硬件和I/O子系统的错误。
CHECKSUM的算法只是根据块的字节值计算一个校验和,算法比较简单。该参数默认在所有表空间上都起作用。
DB_BLOCK_CHECKSUM参数属性
属性 |
描述 |
语法 |
DB_BLOCK_CHECKSUM={OFF|FALSE|TYPICAL|TURE|FULL} |
默认值 |
TYPICAL |
修改范围 |
ALTER SESSION,ALTER SYSTEM |
只有当参数值是TYPICAL或者FULL,并且块的最后一次写是存储了一个校验和时,读取这个块,校验和才会被验证。在FULL模式,Oracle用update/delete语句改变数据之前会验证校验和,改变被应用之后还会重新计算校验和。
从Oracle Database 11g开始,大多数日志校验和都是通过前台进程产生的,同时LGWR执行其余的工作,这是为了更好地发挥CPU和缓存的效率。当这个参数设置为FULL,写日志块到磁盘之前,LGWR验证通过前台进程生成的每个日志块的校验和。在Oracle Database 11g之前的版本中,LGWR独自执行日志块校验和。数据文件块的校验和是由DBWR进程负责计算和管理的。
这个参数设置为OFF时,DBWn只为SYSTEM表空间计算校验和,不为用户表空间计算校验和。另外,此时数据库也不会执行日志的校验工作。
校验和可以使Oracle数据库察觉到磁盘、存储系统或者I/O系统引起的损坏。如果设置为FULL,DB_BLOCK_CHECKSUM也会捕捉在内存中的损坏,并停止它们对磁盘的操作。设置这个参数为TYPICAL值只会引起系统额外的1%~2%的负载,设置为FULL会引起4%~5%的负载。Oracle推荐设置DB_BLOCK_CHECKSUM为TYPICAL。为了保持向后兼容性,TRUE和FALSE值被保留,TRUE等同于TYPICAL,FALSE等同于OFF。
如果DB_BLOCK_CHECKSUM不等于FALSE值,每次读取块,Oracle计算校验和,都与存储在块头中的校验和进行对比。如下例子:
Corrupt block relative dba: 0x0380a58f (file 14,block 42383)
Bad check value found during buffer read
……
参数2 DB_BLOCK_CHECKING
DB_BLOCK_CHECKING参数主要是用于数据块的逻辑一致检查,但只是在块内,不包括块间的逻辑检查。主要用于防止在内存中损坏或数据损坏。
无论该参数如何设置,对SYSTEM表空间来说,逻辑一致检查始终处于“打开”状态,在其他表空间该参数默认是关闭的。
DB_BLOCK_CHECKING参数的属性
参数值 |
含义 |
OFF或者FALSE |
对于用户表空间没有任何逻辑一致性检查工作 |
LOW |
块的内容在内存中改变之后,执行基本的块头检查,如UPDATE语句、INSERT语句、磁盘读或者在RAC中内部实例之间的块传递之后发生检查工作 |
MEDIUM |
除了索引以外的所有对象执行LOW检查和完全语义检查,由于索引能在遭遇损坏的情况下的重建,所以可以不考虑对它检查 |
FULL或者TRUE |
所有对象执行MEDIUM检查和完全语义检查 |
Oracle通过遍历在块中的数据来检查一个块,确保它在逻辑上手尾一致。根据系统负载和参数值,块检查通常一起1%~10%的负载。打开块检查,大量的UPDATE或者INSERT将造成更大负载,对于一个繁忙的系统,特别有大量插入或者更新操作的系统来说,性能影响是比较明显的。如果性能负载可以被接受,应该考虑设置DB_BLOCK_CHECKING为FULL。为了保持向后的兼容性,TURE和FALSE参数值同样可以使用,FALSE等同于OFF,TRUE等同于FULL。
如果启用DB_BLOCK_CHECKING参数,在磁盘的块发生逻辑损坏,下一次块更新将作为软损坏标记这个块,之后读取这个块产生ORA-1578的错误。
n 块错位
当Oracle察觉读取块的内容属于不同块但是校验和又是正确的时,会产生错误。
l 逻辑块损坏
若块包含一个正确的校验和,块头以下的结构是损坏的(块内容损坏),这可能引起不同的ORA-600错误。逻辑块损坏的详细损坏描述通常不会打印到告警日志。DBV将报告块具体的逻辑错误。
3. 坏块的检测工具
以下为损坏块的检测工具和使用方法:
l DBVERIRY坏块验证工具
DBVERIRY不能验证联机Redo日志、归档Redo日志、控制文件和RMAN备份集,只能用于数据文件的块验证。
n DBV验证传统数据文件
下面是使用DBV工具验证数据文件块的例子:
$ dbv file=/testdb/test01.dbf blocksize=8192
注意:DBV工具除了用于检测数据文件是否有坏块外,也用于获得坏块的详细信息。
n DBV验证裸设备数据文件
DBV要求file后面跟的必须是一个包含扩展名的文件,所以如果数据库使用裸设备作为存储方式,就必须使用ln命令连接裸设备一个带扩展名的文件,然后使用DBV工具通过对链接文件的验证实现对裸设备数据文件的验证。
n DBV验证ASM存储的数据文件
如果是验证存储在ASM中的数据文件则需要指定用户名和密码,如果不指定用户名和密码,将收到DBV-00008:USERID must bu specified for OSM files的报错。下面是使用DBV工具验证存储在ASM中的数据文件的块的例子:
$ dbv file=+DATAFILE/testdb/datafile/test.234.648839 userid=sys/oracle
l ANALYZE命令
Analyze命令的主要目的是通过分析数据库对象,为优化器收集数据库对象的统计量信息,以便优化器生成准确的执行计划。同时,它也能检查某个表或索引是否存在损坏的情况。Analyze执行坏块检查,但是不会标记坏块为corrupt,检测结果保存在USER_DUMP_DEST目录下的用户trace文件中。Analyze语法:
Analyze table/index / validate structure ;
Analyze命令会验证每个数据块、每条记录和索引的完整性。CASCADE关键字表示验证表及其相关的所有索引。与DBVERIFY不同的是,analyze只验证高水位线以下的数据块,analyze不会对未使用的空间进行验证。
SQL> analyze table fengpin.test validate structure;
l RMAN工具
RMAN是一块备份工具,就像一个过滤器,RMAN需要通过缓存过滤每一个块,其中一个特点就是检查块是否被损坏。如果备份的数据库中包含有坏块,将会收到错误
l EXP工具
对于包含坏块的表执行导出操作,会收到相关的错误信息。对于这种情况,在非归档模式无法通过块恢复修复块的情况下,有如下两种处理方法:
方法1:启用10231事件
通过设置10231诊断事件可以在导出的时候让Oracle忽略表损坏的块,10231是Oracle的内部诊断事件,设置在全表扫描时跳过坏块的数据块,只导出包含正确块的数据,之后把表删除,再把导出的表数据导入新表,从而修复该表。
1) 启用10231诊断事件
SQL> alter system set events=’10231 trace name context forever,level 10’;
2) 禁用10231诊断事件:
SQL> alter system set events=’10231 trace name context forever,level 0’;
方法2:使用DBMS_REPAIR包标记损坏的块。
可以使用DBMS_REPAIR包标记损坏的数据库对象,这样在对损坏的对象执行全表扫描的时候会跳过损坏的块。语法如下:
SQL> exec dbms_repair.skip_corrupt_blocks(‘’,’tablename’);
EXP坏块检查有一定的局限性,不会发现如下类型的坏块:
ü HWM(高水位线)以上的坏块
ü 索引中存在的坏块
ü 数据字典中存在的坏块
l Expdp工具
使用expdp工具不会给出坏块的提示,只会将对象正确的数据导出。
4. 块的损坏与恢复
块已经不是Oracle的格式,或者其内部是不一致的,那么这个块就被认为已损坏。块介质恢复是当数据文件是联机时,还原和恢复数据块的技术。如果只有一些块被破坏,那么块介质恢复是较好的恢复选择。
BBED(Block Brower and EDitor)是Oracle的一款内部工具,可以用来直接查看和修改Oracle数据文件块的内容。BBED是一个针对Oracle的二进制编译工具。该工具不受Oracle支持,默认是不生成可执行文件的,在使用钱需要重新编译。
1) 编译BBED
直接在Oracle 11gR2 的环境中编译BBED,将收到以下错误信息:
$ cd $ORACLE_HOME/rdbms/lib
$ make –f ins_rdbms.mk $ORACLE_HOME/rdbms/lib/bbed
……
gcc: /u01/app/oracle/11.2.0/db_1/rdbms/lib/ssbbded.o: No such file or directory
gcc: /u01/app/oracle/11.2.0/db_1/rdbms/lib/sbbdpt.o: No such file or directory
Oracle 11gR2 环境中编译BBED可执行文件所需要的ssbbded.o和sbbdpt.o对象文件被移除,不过可以从Oracle 10g环境中将这两个文件拷贝到Oracle 11g环境中进行编译。
除了将上面的ssbbded.o和sbbdpt.o文件拷贝到Oracle 11g环境外,BBED还需要用到$ORACLE_HOME/rdbms/mesg目录下的bbedus.msg和bbedus.msb两个信息文件,这几个文件都需要从Oracle 10g中拷贝到Oracle 11g中对应的目录中。下面是将以上4个文件从Oracle 10g中拷贝到Oracle 11g对应目录之后的编译过程:
$ cd $ORACLE_HOME/rdbms/lib
$ make –f ins_rdbms.mk $ORACLE_HOME/rdbms/lib/bbed
$ file bbed
$ size bbed
$ ldd bbed
$ cp bbed $ORACLE_HOME/bin/
$ cd /
$ which bbed
/u01/app/oracle/product/11.2.0/db_1/bin/bbed
编译成功后登录BBED,登录时需要密码(默认密码是:blockedit)
$ bbed
2) BBED模拟表数据块的损坏
a. 创建测试表
SQL> create table test.testbbed as select * from dba_tables;
b. 创建BBED参数文件
由于BBED无法对ASM进行操作,所以这里将表创建到ACFS文件系统的存储设备上。这里创建两个BBED参数文件,filelist.txt保存要操作的数据文件的ID和路径,bbed.par保存数据文件的块大小、filelist.txt的位置和操作模式:
$ more filelist.txt
6 /testbbed/tbtbs01.dbf
$ more bbed.par
blocksize=8192
listfile=filelist.txt
mode=edit
filelist.txt的内容可通过select file_id,file_name from dba_data_filesSQL查询得到。
c. BBED基本操作
ü 使用指定的参数文件登录BBED:
$ bbed parfile=bbed.par
ü 显示BBED配置文件中指定的数据文件信息:
BBED> info
ü 设置要操作的数据文件:
BBED> set file 6
ü 显示要操作的数据文件的详细信息:
BBED> show
d. 模拟坏块
修改文件号为6的第136号块:
BBED> modify 1000 file 6 block 136
如果修改错误,可以执行revert命令回滚。
e. 验证坏块
在BBED执行以下命令验证数据块,发现block 136已经损坏
BBED> verify
f. 使用DBV工具验证
使用DBV工具验证发现file 6 block 136已经损坏
$ dbv file=/testbbed/tbtbs01.dbf blocksize=8192
g. 执行块读取操作
执行一个test.testbbed的全表扫描,收到ORA-01578错误
SQL> alter system flush buffer_cache;
SQL> select /*+FULL(T)*/ COUNT(1) FROM TEST.TESTBBED T;
3) RMAN的块恢复
块介质恢复用来恢复一个单独的块或者数据文件中数据块的集合,如果是小数据量的数据丢失或损坏,而不是整个数据文件,这种类型的恢复是很有用的。通常,块损坏会在跟踪文件中报告错误信息。
块级别的数据丢失通常是由以下两个原因造成的:
n I/O错误引起的镜像数据丢失。
n 内存损坏,刷新到磁盘。
a. 使用RMAN BLOCKRECOVER命令的注意事项
n 目标数据库必须在MOUNT或者OPEN状态,如果执行某个数据文件的块介质恢复,那么该数据文件不能是脱机状态。
n 块介质恢复不支持基于时间点的块恢复。
n 只能在损坏的块上执行块介质恢复。
n 块被标记为介质损坏之后是不能访问的,直达恢复完成。
n 当使用备份的控制文件加载数据库时,不能执行块的介质恢复。
n 必须有一个包含损坏块文件的全备份,块介质恢复不能使用增量备份。
n 如果RMAN访问块介质恢复需要特定归档Redo日志文件失败,那么将执行还原FAILOVER,尝试使用RMAN资料库中列出的适合这个操作的所有其它备份,如果没有合适的备份存在执行才会失败。
n 数据文件头不能被恢复
n 不能在非归档模式下执行块介质恢复。
b. RMAN BLOCKRECOVER命令的使用方式
RMAN BLOCKRECOVER命令有以下三种使用方式:
方式1 使用BLOCKRECOVER CORRUPTION LIST命令恢复在V$DATABASE_BLOCK_CORRUPTION视图中报告的所有块:
RMAN> blockrecover corruption list;
方式2 使用BLOCKRECOVER 命令的时候指定文件号和块号:
RMAN> blockrecover datafile block ;
方式3 执行blockrecover命令的时候指定表空间和数据块地址(DBA):
RMAN> blockrecover tablespace DBA ;
c. RMAN BLOCKRECOVER使用的例子
例子1 恢复3个数据文件的损坏块:
RMAN> BLOCKRECOVER DATAFILE 2 BLOCK 12,13 DATAFILE 3 BLOCK 5,98,99 DATAFILE 4 BLOCK 19;
例子2:从数据文件拷贝中还原、恢复一系列块:
RMAN> RUN
{
BLOCKRECOVER DATAFILE 3 BLOCK 2,3,4,5 TABLESPACE sales DBA 4194405,4194409,4194412 from DATAFILECOPY;
}
例子3:从指定的tag备份总还原、恢复块
RMAN> BLOCKRECOVER TABLESPACE SYSTEM DBA 4194404,4194405 FROM TAG “weekly_backup”;
例子4:从用于恢复数据到两天以前的备份中还原、恢复SYSTEM表空间中的两个块:
RMAN> BLOCKRECOVER TALBESPACE SYSTEM DBA 4194404,4194405 RESOTRE UNTILL TIME ‘sysdate-2’;
例子5:运行备份验证数据库,修复在V$DATABASE_BLOCK_CORRUPTION中记录的所有损坏块:
RMAN> BACKUP VALIDATE DATABASE;
RMAN> BLOCKRECOVER CORRUPTION LIST;
4) 确定损坏块对应的对象
要确定一个损坏的对象需要知道AFN(Absolute File Numbe,绝对文件号)和BL(Block Number,块号)。AFN和RFN(Relative File Number,相对文件号)通常是相同的,但是也可能不同(特别是如果数据库从Oracle7迁移或者如果使用的是可传输、可插拔的表空间),获得正确的AFN和RFN就显得非常重要,如果指定了错误的AFN将导致找不到对象或错误识别对象。
a. 确定AFN和BL
方法1:从ORA-1578得到AFN
ORA-1578之后产生的ORA-1110错误提供AFN号码。
方法2:从DBVERIFY输出获得AFN。
通过使用DBV工具会报告损坏的块,DBV工具通过提供与相关的RDBA、RFN和BL信息。
方法3:从RMAN获得AFN
RMAN在V$DATABASE_BLOCK_CORRUPTION视图报告损坏的块。该视图的字段FILE#表示AFN,字段BLOCK#表示BL。
b. 定位损坏的对象
一旦AFN被识别,执行以下SQL语句定位损坏的对象:
SQL> select *
From DBA_EXTENTS
Where file_id=&AFN
And &BL BETWEEN BLOCK_ID AND BLOCK_ID + BLOCKS-1;
基于RMAN实现坏块介质恢复(blockrecover)
对于物理损坏的数据块,我们可以通过RMAN块介质恢复(BLOCK MEDIA RECOVERY)功能来完成受损块的恢复,而不需要恢复整个数据库或所有文件来修复这些少量受损的数据块。恢复整个数据库或数据文件那不是大炮用来打蚊子,有点不值得!但前提条件是你得有一个可用的RMAN备份存在,因此,无论何时备份就是一切。本文演示了产生坏块即使用RMAN实现坏块恢复的全过程。
1、创建演示环境
- SQL> select * from v$version where rownum<2;
- BANNER
- --------------------------------------------------------------------------------
- Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production
- --创建用于演示的data file
- SQL> create tablespace tbs_tmp datafile '/u02/database/usbo/oradata/tbs_tmp.dbf' size 10m autoextend on;
- SQL> conn scott/tiger;
- --基于新的数据文件创建对象tb_tmp
- SQL> create table tb_tmp tablespace tbs_tmp as select * from dba_objects;
- SQL> col file_name format a60
- SQL> select file_id,file_name from dba_data_files where tablespace_name='TBS_TMP';
- FILE_ID FILE_NAME
- ---------- ------------------------------------------------------------
- 6 /u02/database/usbo/oradata/tbs_tmp.dbf
- --表对象tb_tmp上的信息,包含对应的文件信息,头部块,总块数
- SQL> select segment_name , header_file , header_block,blocks
- 2 from dba_segments
- 3 where segment_name = 'TB_TMP' and owner='SCOTT';
- SEGMENT_NAME HEADER_FILE HEADER_BLOCK BLOCKS
- ------------------------------ ----------- ------------ ----------
- TB_TMP 6 130 1152
- --首先使用rman备份对应的数据文件
- $ $ORACLE_HOME/bin/rman target /
- RMAN> backup datafile 6 tag=health;
- Starting backup at 2013/08/28 17:03:15
- allocated channel: ORA_DISK_1
- channel ORA_DISK_1: SID=24 device type=DISK
- channel ORA_DISK_1: starting full datafile backup set
- channel ORA_DISK_1: specifying datafile(s) in backup set
- input datafile file number=00006 name=/u02/database/usbo/oradata/tbs_tmp.dbf
- channel ORA_DISK_1: starting piece 1 at 2013/08/28 17:03:16
- channel ORA_DISK_1: finished piece 1 at 2013/08/28 17:03:17
- piece handle=/u02/database/usbo/fr_area/USBO/backupset/2013_08_28/o1_mf_nnndf_HEALTH_91vh6ntb_.bkp tag=HEALTH comment=NONE
- channel ORA_DISK_1: backup set complete, elapsed time: 00:00:01
- Finished backup at 2013/08/28 17:03:17
- RMAN> exit
2、单块数据块损坏的恢复处理
- --下面使用了linux自带的dd命令来损坏单块数据块
- [oracle@linux1 ~]$ dd of=/u02/database/usbo/oradata/tbs_tmp.dbf bs=8192 conv=notrunc seek=130 <<EOF
- > Corrupted block!
- > EOF
- 0+1 records in
- 0+1 records out
- 17 bytes (17 B) copied, 0.000184519 seconds, 92.1 kB/s
- --清空buffer cache
- SQL> alter system flush buffer_cache;
- --查询表对相 tb_tmp,收到ORA-01578
- SQL> select count(*) from tb_tmp;
- select count(*) from tb_tmp
- *
- ERROR at line 1:
- ORA-01578: ORACLE data block corrupted (file # 6, block # 130)
- ORA-01110: data file 6: '/u02/database/usbo/oradata/tbs_tmp.dbf'
- --查询视图v$database_block_corruption,提示有坏块,注意该视图可能不会返回任何数据,如无返回,先执行backup validate
- SQL> select * from v$database_block_corruption;
- FILE# BLOCK# BLOCKS CORRUPTION_CHANGE# CORRUPTIO
- ---------- ---------- ---------- ------------------ ---------
- 6 129 1 0 CORRUPT
- --也可以使用dbv工具来校验坏块,参考: http://blog.csdn.net/robinson_0612/article/details/6530890
- --下面使用blockrecover来恢复坏块
- RMAN> blockrecover datafile 6 block 130;
- Starting recover at 2013/08/28 17:22:25
- using target database control file instead of recovery catalog
- allocated channel: ORA_DISK_1
- channel ORA_DISK_1: SID=24 device type=DISK
- channel ORA_DISK_1: restoring block(s)
- channel ORA_DISK_1: specifying block(s) to restore from backup set
- restoring blocks of datafile 00006
- channel ORA_DISK_1: reading from backup piece /u02/database/usbo/fr_area/USBO/backupset/2013_08_28/o1_mf_nnndf_HEALTH_91vh6ntb_.bkp
- channel ORA_DISK_1: piece handle=/u02/database/usbo/fr_area/USBO/backupset/2013_08_28/o1_mf_nnndf_HEALTH_91vh6ntb_.bkp tag=HEALTH
- channel ORA_DISK_1: restored block(s) from backup piece 1
- channel ORA_DISK_1: block restore complete, elapsed time: 00:00:01
- starting media recovery
- media recovery complete, elapsed time: 00:00:03
- Finished recover at 2013/08/28 17:22:31
- --再次查询表tb_emp正常
- SQL> select count(*) from tb_tmp;
- COUNT(*)
- ----------
- 72449
3、多块数据块损坏的恢复处理
- --下面使用linux dd命令对不连续块损坏
- [oracle@linux1 ~]$ dd of=/u02/database/usbo/oradata/tbs_tmp.dbf bs=8192 conv=notrunc seek=133 <<EOF
- > New corrupted block!
- > EOF
- 0+1 records in
- 0+1 records out
- 21 bytes (21 B) copied, 0.000182835 seconds, 115 kB/s
- [oracle@linux1 ~]$ dd of=/u02/database/usbo/oradata/tbs_tmp.dbf bs=8192 conv=notrunc seek=143 <<EOF
- > New corrupted block!
- > EOF
- 0+1 records in
- 0+1 records out
- 21 bytes (21 B) copied, 0.000115527 seconds, 182 kB/s
- [oracle@linux1 ~]$ dd of=/u02/database/usbo/oradata/tbs_tmp.dbf bs=8192 conv=notrunc seek=153 <<EOF
- > New corrupted block!
- > EOF
- 0+1 records in
- 0+1 records out
- 21 bytes (21 B) copied, 0.000335781 seconds, 62.5 kB/s
- SQL> alter system flush buffer_cache;
- --下面提示块133被损坏,注意我们损坏了多块数据块,但查询时,从块号最小的开始提示,如133被修复后还有坏块则继续提示133之后的坏块
- SQL> select count(*) from scott.tb_tmp;
- select count(*) from scott.tb_tmp
- *
- ERROR at line 1:
- ORA-01578: ORACLE data block corrupted (file # 6, block # 133)
- ORA-01110: data file 6: '/u02/database/usbo/oradata/tbs_tmp.dbf'
- --查询视图v$database_block_corruption无任何记录
- SQL> select * from v$database_block_corruption;
- no rows selected
- --下面使用backup validate来校验数据文件
- RMAN> backup validate datafile 6;
- Starting backup at 2013/08/29 09:42:04
- using target database control file instead of recovery catalog
- allocated channel: ORA_DISK_1
- channel ORA_DISK_1: SID=22 device type=DISK
- channel ORA_DISK_1: starting full datafile backup set
- channel ORA_DISK_1: specifying datafile(s) in backup set
- input datafile file number=00006 name=/u02/database/usbo/oradata/tbs_tmp.dbf
- channel ORA_DISK_1: backup set complete, elapsed time: 00:00:01
- List of Datafiles
- =================
- File Status Marked Corrupt Empty Blocks Blocks Examined High SCN
- ---- ------ -------------- ------------ --------------- ----------
- 6 FAILED 0 223 1408 838489 --字段Status为FAILED
- File Name: /u02/database/usbo/oradata/tbs_tmp.dbf
- Block Type Blocks Failing Blocks Processed
- ---------- -------------- ----------------
- Data 0 1029
- Index 0 0
- Other 3 156 --有3个Blocks Failing
- validate found one or more corrupt blocks
- See trace file /u02/database/usbo/diag/rdbms/usbo/usbo/trace/usbo_ora_27874.trc for details
- Finished backup at 2013/08/29 09:42:06
- --再次查询v$database_block_corruption,表明有3个损坏的块
- SQL> select * from v$database_block_corruption;
- FILE# BLOCK# BLOCKS CORRUPTION_CHANGE# CORRUPTIO
- ---------- ---------- ---------- ------------------ ---------
- 6 153 1 0 CORRUPT
- 6 143 1 0 CORRUPT
- 6 133 1 0 CORRUPT
- --下面直接使用blockrecover corruption list来恢复,如下所有刚刚被校验的坏块都会被恢复
- RMAN> blockrecover corruption list;
- Starting recover at 2013/08/29 10:05:24
- using channel ORA_DISK_1
- channel ORA_DISK_1: restoring block(s)
- channel ORA_DISK_1: specifying block(s) to restore from backup set
- restoring blocks of datafile 00006
- channel ORA_DISK_1: reading from backup piece /u02/database/usbo/fr_area/USBO/backupset/2013_08_28/o1_mf_nnndf_HEALTH_91vh6ntb_.bkp
- channel ORA_DISK_1: piece handle=/u02/database/usbo/fr_area/USBO/backupset/2013_08_28/o1_mf_nnndf_HEALTH_91vh6ntb_.bkp tag=HEALTH
- channel ORA_DISK_1: restored block(s) from backup piece 1
- channel ORA_DISK_1: block restore complete, elapsed time: 00:00:01
- starting media recovery
- media recovery complete, elapsed time: 00:00:03
- Finished recover at 2013/08/29 10:05:28
- --校验结果
- SQL> select count(*) from scott.tb_tmp;
- COUNT(*)
- ----------
- 72449
4、坏块的对象定位与影响
- --下面我们查询块号为163上的对象
- SQL> select dbms_rowid.rowid_object(rowid) object_id,dbms_rowid.rowid_relative_fno(rowid) file_id,
- 2 dbms_rowid.rowid_block_number(rowid) block_id,owner,object_name,object_id
- 3 from scott.tb_tmp where dbms_rowid.rowid_block_number(rowid)=163 and rownum<=2;
- OBJECT_ID FILE_ID BLOCK_ID OWNER OBJECT_NAME OBJECT_ID
- ---------- ---------- ---------- ------------ ------------------------------ ----------
- 74555 6 163 SYS GV_$QUEUEING_MTH 2439
- 74555 6 163 PUBLIC GV$QUEUEING_MTH 2440
- --使用上面的方法,我们损块块163,173,此处不再列出
- a、对于坏块对象无法进行聚合汇总等操作
- SQL> select count(*) from scott.tb_tmp;
- select count(*) from scott.tb_tmp
- *
- ERROR at line 1:
- ORA-01578: ORACLE data block corrupted (file # 6, block # 163)
- ORA-01110: data file 6: '/u02/database/usbo/oradata/tbs_tmp.dbf'
- b、对于坏块上的记录无法被查询
- --我们使用基于之前查询到的OBJECT_ID来查询
- SQL> select owner,object_name,object_id from scott.tb_tmp where object_id in(2439,2440);
- select owner,object_name,object_id from scott.tb_tmp where object_id in(2439,2440)
- *
- ERROR at line 1:
- ORA-01578: ORACLE data block corrupted (file # 6, block # 163)
- ORA-01110: data file 6: '/u02/database/usbo/oradata/tbs_tmp.dbf'
- --如下面的查询,位于损坏块上的数据无法被查询到,但对于未损坏的依旧可以查询。下面的查询时块161上的对象
- SQL> select owner,object_name,object_id from scott.tb_tmp
- 2 where dbms_rowid.rowid_block_number(rowid)=161 and rownum<3;
- OWNER OBJECT_NAME OBJECT_ID
- ------------------------------ ------------------------------ ----------
- PUBLIC GV$RECOVERY_LOG 2285
- SYS GV_$ARCHIVE_GAP 2286
- --Author : Robinson Cheng
- --Blog : http://blog.csdn.net/robinson_0612
- c、定位受损块所对应的对象
- SQL> run get_obj_name_from_corrupt_block
- 1 SELECT tablespace_name,
- 2 segment_type,
- 3 owner,
- 4 segment_name,
- 5 partition_name
- 6 FROM dba_extents
- 7* WHERE file_id = &file_id AND &block_id BETWEEN block_id AND block_id + blocks - 1
- Enter value for file_id: 6
- Enter value for block_id: 133
- old 7: WHERE file_id = &file_id AND &block_id BETWEEN block_id AND block_id + blocks - 1
- new 7: WHERE file_id = 6 AND 133 BETWEEN block_id AND block_id + blocks - 1
- TABLESPACE_NAME SEGMENT_TYPE OWNER SEGMENT_NAME PARTITION_NAME
- ------------------------------ ------------------ -------------- ----------------- -----------------
- TBS_TMP TABLE SCOTT TB_TMP
- d、对于损坏的数据文件,缺省情况下,不能对其进行备份,如下
- RMAN> backup datafile 6 tag='corruption';
- Starting backup at 2013/08/29 10:37:32
- 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=00006 name=/u02/database/usbo/oradata/tbs_tmp.dbf
- channel ORA_DISK_1: starting piece 1 at 2013/08/29 10:37:32
- RMAN-00571: ===========================================================
- RMAN-00569: =============== ERROR MESSAGE STACK FOLLOWS ===============
- RMAN-00571: ===========================================================
- RMAN-03009: failure of backup command on ORA_DISK_1 channel at 08/29/2013 10:37:33
- ORA-19566: exceeded limit of 0 corrupt blocks for file /u02/database/usbo/oradata/tbs_tmp.dbf
- --需要设定允许损坏块的数量之后才能进行备份
- RMAN> run{
- 2> set maxcorrupt for datafile 6 to 2;
- 3> backup datafile 6 tag='corruption';
- 4> }
- executing command: SET MAX CORRUPT
- Starting backup at 2013/08/29 10:41:24
- 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=00006 name=/u02/database/usbo/oradata/tbs_tmp.dbf
- channel ORA_DISK_1: starting piece 1 at 2013/08/29 10:41:25
- channel ORA_DISK_1: finished piece 1 at 2013/08/29 10:41:26
- piece handle=/u02/database/usbo/fr_area/USBO/backupset/2013_08_29/o1_mf_nnndf_CORRUPTION_91xf6o18_.bkp tag=CORRUPTION comment=NONE
- channel ORA_DISK_1: backup set complete, elapsed time: 00:00:01
- Finished backup at 2013/08/29 10:41:26
- --查看备份信息如下,应在修复坏块后重新备份以避免由于保留策略导致先前可用的备份被aged out
- RMAN> list backup summary;
- List of Backups
- ===============
- Key TY LV S Device Type Completion Time #Pieces #Copies Compressed Tag
- ------- -- -- - ----------- ------------------- ------- ------- ---------- ---
- 1 B F A DISK 2013/08/28 17:03:17 1 1 NO HEALTH
- 3 B F A DISK 2013/08/29 10:41:25 1 1 NO CORRUPTION
5、后记
a、对于受损的数据块,仅仅坏块上的数据无法被查询或读取,其余正常块的数据依旧可以使用。
b、对于受损的表对象进行聚合等相关运算时收到错误提示,因为坏块上的数据无法被统计。如果你聚合的是索引列,索引未损坏的情形则可正常返回。
c、可以基于RMAN可用的备份文件实现块介质恢复,其数据文件无需offline,开销最小,影响最小。
d、对于多个数据块的损坏,先执行backup validate校验数据库或相应的数据文件以便标记受损的坏块后,填充v$database_block_corruption以及后续恢复。
e、对于使用backup validate 校验后的情形,坏块恢复时可以直接使用blockrecover corruption list一次性恢复所有的坏块。
f、缺省情况下,存在坏块的数据文件无法成功备份,也会导致自动备份脚本失败。
DBVERIFY 工具的使用
--**********************
-- DBVERIFY 工具的使用
--**********************
Oracle 数据库运行过程中由于硬件故障或操作系统故障导致导致Oracle无法以Oracle格式来识别或所包含的内容即为出现数据块损坏
故障,这个坏块可以分为介质损坏以及逻辑损坏。下面给出了块的检查,以及使用DBVERIFY 工具实施块检查。
一、块检查
1.何时检查块
当一个数据块被读或写的时候,将对块的进行一致性检查,检查的内容包括
块的版本
比较块在cache与block buffer中的数据块地址
根据要求进行校验(checksum)
2.损坏的数据块的错误提示
可以从告警日志文件中找到该错误提示,以及在会话中发现损坏的数据块时也会给出类似的提示
ORA-01578: ORACLE data block corrupted (file # 6, block # 11)
ORA-01110: data file 6: '/u01/app/oracle/oradata/orcl/tbs01.dbf'
3.与块损坏的相关特性(几种检查工具)
------------------------------------------------------------------------------------------------
特性 坏块侦测类型 能否修复损坏块
------------------------------------------------------------------------------------------------
DBVERIFY 物理 否
ANALYZE 逻辑 否
DB_BLOCK_CHECKING 逻辑 否
DB_BLOCK_CHECKSUM 物理 否
exp 物理 否
FlashBack 逻辑 是
DBMS_REPAIR 逻辑 是
Block media recovery 未知 是
二、DBVERIFY工具介绍
特性
是一个运行于操作系统提示符下的外部程序,用于验证数据文件,检查块的一致性错误
仅仅针对数据文件,能够校验open阶段的数据文件以及shutdown状态下的数据文件
可以验证复制的数据文件,也可以验证备份的镜像副本
不支持联机日志文件,控制文件,归档日志,RMAN备份集验证
被验证的文件可以位于文件系统,ASM磁盘或原始设备
在Unix系统中位于:$ORACLE_HOME/bin/dbv
在Windows系统中位于:%ORACLE_HOME%/bin/dbv.exe
对于DBVERIFY工具,高版本可以自动识别低版本数据库,比如11g的dbv访问9i的数据库,但是低版本的dbv访问高版本会报错
三、DBVERIFY工具用法
1.获取dbv的帮助信息,直接在提示符下输入dbv即可 或者输入dbv help=y
[oracle@oradb orcl]$ dbv
DBVERIFY: Release 10.2.0.4.0 - Production on Tue Oct 26 18:21:09 2010
Copyright (c) 1982, 2007, Oracle. All rights reserved.
Keyword Description (Default)
----------------------------------------------------
FILE File to Verify (NONE)
START Start Block (First Block of File)
END End Block (Last Block of File)
BLOCKSIZE Logical Block Size (8192)--指定数据文件的尺寸,缺省值为8192,对于非8192块将收到DBV-00103错误
LOGFILE Output Log (NONE) --用于显示验证进度
FEEDBACK Display Progress (0)
PARFILE Parameter File (NONE) --可以指定参数文件
USERID Username/Password (NONE) --校验段、ASM文件需要使用
SEGMENT_ID Segment ID (tsn.relfile.block) (NONE) --校验段,需要表空间ID,数据文件ID,段的头部ID
HIGH_SCN Highest Block SCN To Verify (NONE)
(scn_wrap.scn_base OR scn)
2.校验online,offline数据文件,使用下面的方法
dbv file=<dir>
[oracle@oradb orcl]$ dbv file=$ORACLE_BASE/oradata/orcl/tbs01.dbf
DBVERIFY: Release 10.2.0.4.0 - Production on Tue Oct 26 18:29:39 2010
Copyright (c) 1982, 2007, Oracle. All rights reserved.
DBVERIFY - Verification starting : FILE = /u01/app/oracle/oradata/orcl/tbs01.dbf
DBVERIFY - Verification complete
Total Pages Examined : 128 --校验的总页面数,一个页面即是一个数据块
Total Pages Processed (Data) : 96 --已处理的数据页面数
Total Pages Failing (Data) : 0 --已处理数据页面的失败数
Total Pages Processed (Index): 1 --已处理的索引页面数
Total Pages Failing (Index): 0 --已处理索引页面失败数
Total Pages Processed (Other): 31 --已处理的其它页面数
Total Pages Processed (Seg) : 0
Total Pages Failing (Seg) : 0
Total Pages Empty : 0
Total Pages Marked Corrupt : 0
Total Pages Influx : 0
Highest block SCN : 1152518 (0.1152518)
注意:如果Total Pages Influx的值大于零,且未存在坏块的情况下,是由于针对open状态的文件运行dbv
程序遇到了一个当前正在被DBWn进程写入的数据块
[oracle@oradb orcl]$ dbv file=$ORACLE_BASE/oradata/orcl/tbs01.dbf feedback=1000
上面这句在执行时每验证1000个块将显示一个"."号
--下面的校验发现了I/O错误
[oracle@oradb orcl]$ dbv file=/u01/app/oracle/oradata/orcl/tbs01.dbf
DBVERIFY: Release 10.2.0.4.0 - Production on Tue Oct 26 18:26:21 2010
Copyright (c) 1982, 2007, Oracle. All rights reserved.
DBV-00102: File I/O error on FILE (/u01/app/oracle/oradata/orcl/tbs01.dbf)
during end read operation (-1)
3.验证指定段
该方法需要获得段所在表空间的ID,段所在数据文件的ID,段的头部ID
如下面的查询表空间的ID为7,文件ID为6,段的头部ID为35
sys@ORCL> select tablespace_id,tablespace_name,header_file,header_block
2 from sys_dba_segs
3 where segment_name='TB3';
TABLESPACE_ID TABLESPACE_NAME HEADER_FILE HEADER_BLOCK
------------- --------------- ----------- ------------
7 TBS1 6 35
注意:sys用户的段可以查询sys_user_segs,而普通用户的段信息,需要查询sys_dba_segs
[oracle@oradb orcl]$ dbv userid=scott/tiger segment_id=7.6.35
DBVERIFY: Release 10.2.0.4.0 - Production on Tue Oct 26 18:50:01 2010
Copyright (c) 1982, 2007, Oracle. All rights reserved.
DBVERIFY - Verification starting : SEGMENT_ID = 7.6.35
DBVERIFY - Verification complete
Total Pages Examined : 8
Total Pages Processed (Data) : 5
Total Pages Failing (Data) : 0
Total Pages Processed (Index): 0
Total Pages Failing (Index): 0
Total Pages Processed (Other): 2
Total Pages Processed (Seg) : 1
Total Pages Failing (Seg) : 0
Total Pages Empty : 0
Total Pages Marked Corrupt : 0
Total Pages Influx : 0
Highest block SCN : 1152518 (0.1152518)
4.验证复制的数据文件或验证备份的镜像副本
RMAN> backup as copy datafile 6 --使用RMAN备份镜像副本
2> format='/u01/app/oracle/bk/rmbk/cp_dfile6'
3> tag='Copy_datafile6';
[oracle@oradb orcl]$ dbv file=/u01/app/oracle/bk/rmbk/cp_dfile6
DBVERIFY: Release 10.2.0.4.0 - Production on Tue Oct 26 18:59:17 2010
Copyright (c) 1982, 2007, Oracle. All rights reserved.
DBVERIFY - Verification starting : FILE = /u01/app/oracle/bk/rmbk/cp_dfile6
DBVERIFY - Verification complete
Total Pages Examined : 128
Total Pages Processed (Data) : 96
Total Pages Failing (Data) : 0
Total Pages Processed (Index): 1
Total Pages Failing (Index): 0
Total Pages Processed (Other): 31
Total Pages Processed (Seg) : 0
Total Pages Failing (Seg) : 0
Total Pages Empty : 0
Total Pages Marked Corrupt : 0
Total Pages Influx : 0
Highest block SCN : 1152518 (0.1152518)
RMAN命令中的BACKUP VALIDATE DATABASE命令通常用于检查全库,该命令不产生任何备份集,可以通过
Validate命令来检查是否能备份,如数据文件是否存在,是否存在坏块不能被备份,查询视图
v$database_block_corruption,此视图将检查过程中存在的坏块
如使用下面的查询
RMAN> backup validate database;
RMAN> backup validate database archivelog all;
sys@ORCL> select * from v$database_block_corruption;
no rows selected
视图v$database_block_corruption将列出损坏的坏块所在的文件位置,损坏块的起始位置,损坏快的大
小以及损坏类型如果上述视图中发现了坏块,则可以通过SQL查询获得坏块所影响的范围,以及确定坏块
所影响的是索引段还是UNDO段
select owner,segment_name,segment_type from dba_extents where file_id=<F> and <B>
between block_id and block_id+blocks-1;
(<F>和<B>分别是ORA-01578报出的坏块出现的文件号和块号)
下面使用rman 来修复受损的数据块
RMAN> run{
2> allocate channel ch1 device type disk;
3> blockrecover datafile 6 block 37;
4> release channel ch1;}
released channel: ORA_DISK_1
allocated channel: ch1
channel ch1: sid=139 devtype=DISK
Starting blockrecover at 26-OCT-10
starting media recovery
media recovery complete, elapsed time: 00:00:00
Finished blockrecover at 26-OCT-10
released channel: ch1
flasher@ORCL> alter table tb3 add constraint empno_tb3_pk
2 primary key(empno);
四、其它
1.事实上使用dbv工具可以对控制文件进行验证(数据库处于OPEN状态),参见下面的例子
[oracle10g:oracle:orcl]$ dbv file=control01.ctl
DBVERIFY: Release 10.2.0.4.0 - Production on Sun Jun 5 14:56:31 2011
Copyright (c) 1982, 2007, Oracle. All rights reserved.
DBV-00103: Specified BLOCKSIZE (8192) differs from actual (16384) --根据提示知道blocksize的值为16384
[oracle@oradb orcl]$ dbv file=control01.ctl blocksize=16384
DBVERIFY: Release 10.2.0.4.0 - Production on Sun Jun 5 14:53:01 2011
Copyright (c) 1982, 2007, Oracle. All rights reserved.
DBVERIFY - Verification starting : FILE = control01.ctl
DBVERIFY - Verification complete
Total Pages Examined : 404
Total Pages Processed (Data) : 0
Total Pages Failing (Data) : 0
Total Pages Processed (Index): 0
Total Pages Failing (Index): 0
Total Pages Processed (Other): 40
Total Pages Processed (Seg) : 0
Total Pages Failing (Seg) : 0
Total Pages Empty : 364
Total Pages Marked Corrupt : 0
Total Pages Influx : 0
Highest block SCN : 775 (65535.775)
2.对联机日志文件的验证(数据库处于OPEN状态),不支持
[oracle10g:oracle:orcl]$ dbv file=redo01.log
DBVERIFY: Release 10.2.0.4.0 - Production on Sun Jun 5 15:01:09 2011
Copyright (c) 1982, 2007, Oracle. All rights reserved.
DBV-00103: Specified BLOCKSIZE (8192) differs from actual (512)
[oracle10g:oracle:orcl]$ dbv file=redo01.log blocksize=512 --可以执行,但出现下面很多的提示(介质错误)
Page 88441 is influx - most likely media corrupt
Corrupt block relative dba: 0x00015979 (file 0, block 88441)
Fractured block found during dbv:
Data in bad block:
type: 1 format: 2 rdba: 0x00015979
last change scn: 0x8010.00000010 seq: 0x51 flg: 0x55
spare1: 0x0 spare2: 0x0 spare3: 0x0
consistency value in tail: 0xc2037800
check value in block header: 0x108
computed block checksum: 0x0
About Me
...............................................................................................................................
● 本文整理自网络
● 本文在itpub(http://blog.itpub.net/26736162)、博客园(http://www.cnblogs.com/lhrbest)和个人微信公众号(xiaomaimiaolhr)上有同步更新
● 本文itpub地址:http://blog.itpub.net/26736162/abstract/1/
● 本文博客园地址:http://www.cnblogs.com/lhrbest
● 本文pdf版及小麦苗云盘地址:http://blog.itpub.net/26736162/viewspace-1624453/
● 数据库笔试面试题库及解答:http://blog.itpub.net/26736162/viewspace-2134706/
● QQ群:230161599 微信群:私聊
● 联系我请加QQ好友(646634621),注明添加缘由
● 于 2017-05-09 09:00 ~ 2017-05-30 22:00 在魔都完成
● 文章内容来源于小麦苗的学习笔记,部分整理自网络,若有侵权或不当之处还请谅解
● 版权所有,欢迎分享本文,转载请保留出处
...............................................................................................................................
拿起手机使用微信客户端扫描下边的左边图片来关注小麦苗的微信公众号:xiaomaimiaolhr,扫描右边的二维码加入小麦苗的QQ群,学习最实用的数据库技术。