Oracle数据库坏块(corruption)-物理坏块




概述

-------------

数据库坏块(corruption) 的类型可以按照坏块所属对象的不同,分为用户数据坏块,数据字典坏块,Undo坏块,控制文件坏块,Redo坏块,Lob坏块,index坏块等等;也可以按照坏块产生的原因,分为物理坏块(physical corruption)和逻辑坏块(logical corruption )。

本文主要讨论用户数据发生物理坏块(physical corruption)分析和解决方法。


物理坏块

-------------

常见的物理坏块(Physical Block Corruptions)有块头和块尾信息不一致(Fractured/Incomplete),checksum值无效,数据块信息全部为0等情况,并且可能伴随错误ORA-1578和ORA-1110



为了及时发现物理坏块和准确定位坏块产生的原因,oracle建议设置初始化参数DB_BLOCK_CHECKSUM=TYPICAL(默认值)。一般情况下,物理坏块是由于底层OS/disk系统错误/损坏,导致数据块被修改,数据块标志为坏块(corruption)。



Case分享

-------------

数据块的Checksum值无效是一种常见的物理坏块,当数据库初始化参数DB_BLOCK_CHECKSUM=TYPICAL(默认值)时,DBWR进程将数据块写入disk时会计算数据块的Checksum,并且将Checksum值记录在数据块的位置offset 16和17;当从disk读取该数据块时,oracle重新计算数据块的Checksum,并且与记录在数据块中的Checksum做异或运算(Xor),如果异或结果为非0,说明数据块被修改过,数据块为坏块(corruption)。



1. 当前数据库初始化参数配置DB_BLOCK_CHECKSUM=TYPICAL,因此从disk读取数据块时校验checksum:

SQL> show parameter DB_BLOCK_CHECKSUM



NAME                                 TYPE        VALUE

------------------------------------ ----------- ------------------------------

db_block_checksum                    string      TYPICAL



2. 查询表dept时发现有坏块,报错信息ORA-1578和ORA-1110,坏块为file # 4, block # 133



SQL> select * from dept;

 select * from dept

*

ERROR at line 1:

ORA-01578: ORACLE data block corrupted (file # 4, block # 133)

ORA-01110: data file 4: '/u01/app/oracle/oradata/orcl/users01.dbf'



3. 出现以上错误的同时在alert log中也有详细错误信息,这些错误信息说明数据块(file # 4, block # 133)损坏的原因是checksum无效。数据块中记录的checksum值为0x8167(这个值是上一次DBWR写入磁盘时计算的),读取数据块时重新计算得到的checksum是0x8122,checksum值异或运算(Xor)的结果是0x45 (computed block checksum)。由于两次checksum值不同(即异或结果为非0),说明数据块被修改过,数据块为坏块(corruption)。



Alert log错误信息:

Hex dump of (file 4, block 133) in trace file /u01/app/oracle/diag/rdbms/orcl/orcl/trace/orcl_ora_20892.trc

Corrupt block relative dba: 0x01000085 (file 4, block 133)

Bad check value found during multiblock buffer read  <<<<<<<<<<<<<< 说明坏块的原因是checksum无效

Data in bad block:

 type: 6 format: 2 rdba: 0x01000085

 last change scn: 0x0000.0023d69a seq: 0x5 flg: 0x06

 spare1: 0x0 spare2: 0x0 spare3: 0x0

 consistency value in tail: 0xd69a0605

 check value in block header: 0x8167   <<<<<<<<<<<<<< 数据块中记录的checksum值为0x8167

 computed block checksum: 0x45         <<<<<<<<<<<<<< 0x8167与0x8122异或运算(Xor)的结果是0x45

Reading datafile '/u01/app/oracle/oradata/orcl/users01.dbf' for corruption at rdba: 0x01000085 (file 4, block 133)

Reread (file 4, block 133) found same corrupt data (no logical check)

Sun Mar 23 22:53:40 2014

Corrupt Block Found

         TSN = 4, TSNAME = USERS

         RFN = 4, BLK = 133, RDBA = 16777349

         OBJN = 14343, OBJD = 14343, OBJECT = DEPT, SUBOBJECT = 

         SEGMENT OWNER = JAMES, SEGMENT TYPE = Table Segment         <<<<<<<<<<<<<< 坏块对应的object ID

Errors in file /u01/app/oracle/diag/rdbms/orcl/orcl/trace/orcl_ora_20892.trc  (incident=182595):

ORA-01578: ORACLE data block corrupted (file # 4, block # 133)

ORA-01110: data file 4: '/u01/app/oracle/oradata/orcl/users01.dbf'



4.1 对应的orcl_ora_20892.trc中也有数据块的信息,其中数据块上记录的checksum值是0x8167(chkval)

Block dump from disk:

buffer tsn: 4 rdba: 0x01000085 (4/133)

scn: 0x0000.0023d69a seq: 0x05 flg: 0x06 tail: 0xd69a0605

frmt: 0x02 chkval: 0x8167 type: 0x06=trans data

Hex dump of block: st=0, typ_found=1


4.2 通过dd也查看数据块中记录的checksum值, offset 16,17 对应的是checksum值0x8167

$ dd if=/u01/app/oracle/oradata/orcl/users01.dbf bs=8192 count=1 skip=133 of=/tmp/dd133.out



$ od -x /tmp/dd133.out

0000000 a206 0000 0085 0100 d69a 0023 0000 0605

0000020 8167 0000 0001 0000 3807 0000 2fef 000c

^^^^



5. 修复数据坏块的方法可以通过备份恢复或者DBMS_REPAIR.SKIP_CORRUPT_BLOCKS跳过坏块。

5.1 方法#1 RMAN数据块恢复:

RMAN> run {blockrecover datafile 4 block 133;}



SQL> select * from dept;



    DEPTNO DNAME          LOC

---------- -------------- -------------

        10 ACCOUNTING     DALIAN

        20 RESEARCH       DALLAS

        30 SALES          CHICAGO

        40 OPERATIONS     BOSTON



5.2 方法#2 DBMS_REPAIR.SKIP_CORRUPT_BLOCKS跳过坏块,然后将dept表中的其他数据导出重建表

SQL> alter session set db_file_multiblock_read_count=1;

SQL> execute DBMS_REPAIR.SKIP_CORRUPT_BLOCKS('JAMES','DEPT'); 


SQL> create table dept_new as select * from dept;

参与此主题的后续讨论,请回复blog,或者访问我们的中文社区,跟帖"分享:Oracle数据库坏块(corruption)-物理坏块"���





评论:

DBMS_REPAIR.SKIP_CORRUPT_BLOCKS('JAMES','DEPT'); 这里跳过的值是如何计算的。如何知道损坏的块的值是'JAMES','DEPT'?

发表于 guest 在 2015年04月10日, 09:18 上午 CST #

发表一条评论:
  • HTML语法: 禁用
About

本博客由Oracle全球技术支持中国区的工程师维护。为中文用户提供数据库相关的技术支持信息,包括常用的诊断工具、诊断方法、产品新特性、案例分析等。此外,MOS也陆续推出各类中文内容:技术通讯统一发布在Note 1529795.1 中,中文文档列表更新在Note 1533057.1 中,网上讲座请查看MOS文档 1456176.1,在"Archived"中可以下载历史的录音和文档。

Search

Archives
« 七月 2015
星期日星期一星期二星期三星期四星期五星期六
   
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
 
       
今天