`

ORACLE坏块(ORA-01578)处理方法

阅读更多
0.模拟出现坏块环境

SQL> CREATE TABLESPACE "TEST"
  2      LOGGING
  3      DATAFILE 'D:\ORACLE\ORADATA\ALAN\TEST.ora' SIZE 1M EXTENT
  4      MANAGEMENT LOCAL SEGMENT SPACE MANAGEMENT  AUTO
  5  /

表空间已创建。

SQL> create user alantest identified by alantest
  2  default tablespace test
  3  temporary tablespace temp;

用户已创建

SQL> grant dba to alantest;

授权成功。

SQL> connect alantest/alantest
已连接。
SQL> show user
USER 为"ALANTEST"
SQL> create table test_alan as select * from dba_objects;

RMAN> backup database format='c:\rmanbackup\FULL_%U';

启动 backup 于 07-7月 -06
正在使用目标数据库控制文件替代恢复目录
分配的通道: ORA_DISK_1
通道 ORA_DISK_1: sid=18 devtype=DISK
通道 ORA_DISK_1: 正在激活 full 数据文件备份集
通道 ORA_DISK_1: 正在指定备份集中的数据文件
在备份集中包含当前的 SPFILE
备份集中包括当前控制檔
输入数据文件 fno=00001 name=D:\ORACLE\ORADATA\ALAN\SYSTEM01.DBF
输入数据文件 fno=00002 name=D:\ORACLE\ORADATA\ALAN\UNDOTBS01.DBF
输入数据文件 fno=00003 name=D:\ORACLE\ORADATA\ALAN\INDX01.DBF
输入数据文件 fno=00005 name=D:\ORACLE\ORADATA\ALAN\USERS01.DBF
输入数据文件 fno=00004 name=D:\ORACLE\ORADATA\ALAN\TOOLS01.DBF
输入数据文件 fno=00006 name=D:\ORACLE\ORADATA\ALAN\CATTAB01.DBF
输入数据文件 fno=00007 name=D:\ORACLE\ORADATA\ALAN\TEST.ORA
通道 ORA_DISK_1: 正在激活段 1 于 07-7月 -06
通道 ORA_DISK_1: 已完成段 1 于 07-7月 -06
段 handle=C:\RMANBACKUP\FULL_0JHNJ63P_1_1 comment=NONE
通道 ORA_DISK_1: 备份集已完成, 经过时间:00:01:38
完成 backup 于 07-7月 -06

SQL> shutdown immediate
数据库已经关闭。
已经卸载数据库。
ORACLE 例程已经关闭。



使用编辑工具修改数据文件 生成坏块



C:\>dbv  file=D:\ORACLE\ORADATA\ALAN\TEST.ora blocksize=8192



DBVERIFY: Release 9.2.0.6.0 - Production on 星期五 7月 7 14:53:46 2006

Copyright (c) 1982, 2002, Oracle Corporation.  All rights reserved.

DBVERIFY - 验证正在开始 : FILE = D:\ORACLE\ORADATA\ALAN\TEST.ora
标记为损坏的页12
***
Corrupt block relative dba: 0x01c0000c (file 7, block 12)
Bad check value found during dbv:
Data in bad block -
type: 6 format: 2 rdba: 0x01c0000c
last change scn: 0x0000.0007bc14 seq: 0x1 flg: 0x04
consistency value in tail: 0xbc140601
check value in block header: 0x91ea, computed block checksum: 0x110e
spare1: 0x0, spare2: 0x0, spare3: 0x0
***
DBVERIFY - 验证完成

检查的页总数         :128
处理的页总数(数据):77
失败的页总数(数据):0
处理的页总数(索引):0
失败的页总数(索引):0
处理的页总数(其它):16
处理的总页数 (段)  : 0
失败的总页数 (段)  : 0
空的页总数            :34
标记为损坏的总页数:1
汇入的页总数           :0
Highest block SCN            : 506930 (0.506930)



1.对相关的表进行操作:

SQL> select * from alantest.test_alan where rownum=1234;
select * from alantest.test_alan where rownum=1234
*
ERROR 位于第 1 行:
ORA-01578: ORACLE 数据块损坏(文件号7,块号12)
ORA-01110: 数据文件 7: 'D:\ORACLE\ORADATA\ALAN\TEST.ORA'

SQL> select count(*) from alantest.test_alan;
select count(*) from alantest.test_alan
                              *
ERROR 位于第 1 行:
ORA-01578: ORACLE 数据块损坏(文件号7,块号12)
ORA-01110: 数据文件 7: 'D:\ORACLE\ORADATA\ALAN\TEST.ORA'



2. 检查alter.log出现的报错信息



Corrupt block relative dba: 0x01c0000c (file 7, block 12)
Bad check value found during buffer read
Data in bad block -
type: 6 format: 2 rdba: 0x01c0000c
last change scn: 0x0000.0007bc14 seq: 0x1 flg: 0x04
consistency value in tail: 0xbc140601
check value in block header: 0x91ea, computed block checksum: 0x91a
spare1: 0x0, spare2: 0x0, spare3: 0x0


3. 确定坏块的对象是什么?

SQL> select tablespace_name,segment_type,segment_name,owner from dba_extents
  2  where file_id=7 and 12 BETWEEN block_id AND block_id+blocks-1;

  TABLESPACE_NAME  SEGMENT_TYPE  SEGMENT_NAME     OWNER

  TEST                             TABLE         TEST_ALAN           ALANTEST



a. file#  block# 可以从错误信息中得到
b. 如果是temp檔中出现坏块 是没有记录返回的
c. 通常容易出现坏块的对象有:
   数据字典(system表空间) 回滚段临时段 联机日志 索引或者分区索引 表



4. 如果通过返回的结果确定坏的是索引段只要把这个索相删除然后重建一下就可以了
   如果出现坏的是表段请继续往下看



5. 具体解决办法



A. 恢复数据文件方法



前提要求:

a.数据库为归档方式
b.有完整的物理备份

步骤:
(1) offline受影响的数据文件 执行以下的语句:

    ALTER DATABASE DATAFILE 7 OFFLINE;

(2) 把旧的数据文件保存后移除

(3) 恢复数据文件 执行以下语句:

    RESTORE DATAFILE 7;
    RECOVER DATAFILE 7;

(4) Online恢复后的数据文件 执行以下的语句:

    ALTER DATABASE DATAFILE 7 ONLINE;


B.只恢复坏的block(9i以上版本可用)



前提要求:

a.要求数据库版本是9.2.0以上
b.数据库为归档方式
c.有完整的物理备份

步骤:

(1) 使用RMAN的BLOCKRECOVER命令:

    Rman>run{
         blockrecover datafile 7 block 12;
         }

RMAN> blockrecover datafile 7 block 12;

启动 blockrecover 于 07-7月 -06
正在使用目标数据库控制文件替代恢复目录
分配的通道: ORA_DISK_1
通道 ORA_DISK_1: sid=16 devtype=DISK


通道 ORA_DISK_1: 正在恢复块
通道 ORA_DISK_1: 正在指定要从备份集恢复的块
正在恢复数据文件 00007 的块
通道 ORA_DISK_1: 已从备份段 1 恢复块
段 handle=C:\RMANBACKUP\FULL_0JHNJ63P_1_1 tag=TAG20060707T132408 params=NULL
通道 ORA_DISK_1: 块恢复已完成

正在开始介质的恢复
完成介质的恢复

完成 blockrecover 于 07-7月 -06

    可以强制使用某个SCN号之前的备份来恢复数据块
    Rman>run{
         blockrecover datafile 7 block 12 restore until sequence 8505;
         }



C.通过ROWID RANGE SCAN 保存资料



步骤:
(1) 通过file# block# 查出出现坏块的object

SQL> select tablespace_name,segment_type,segment_name,owner from dba_extents
  2  where file_id=7 and 12 BETWEEN block_id AND block_id+blocks-1;

  TABLESPACE_NAME  SEGMENT_TYPE SEGMENT_NAME OWNER

  TEST             TABLE        TEST_ALAN    ALANTEST

(2) 构造坏块的ROWID

SQL> SELECT DATA_OBJECT_ID FROM dba_objects where object_name='TEST_ALAN' and owner='ALANTEST';

DATA_OBJECT_ID
--------------
          6627

SQL> SELECT dbms_rowid.rowid_create(1,6627,7,12,0) from DUAL;

DBMS_ROWID.ROWID_C
------------------
AAABnjAAHAAAAAMAAA

SQL> SELECT dbms_rowid.rowid_create(1,6627,7,13,0) from DUAL;

DBMS_ROWID.ROWID_C
------------------
AAABnjAAHAAAAANAAA



Oracle的物理扩展ROWID有18位 每位采用64位编码分别用A~Z、a~z、0~9、+、/共64个字符表示
A表示0,B表示1,……Z表示25,a表示26,……z表示51,0表示52,……,9表示61,+表示62,/表示63 .

ROWID具体划分可以分为4部分。

1.OOOOOO:前6位表示DATA OBJECT NUMBER,将起转化位数字后匹配DBA_OBJECTS中的DATA_OBJECT_ID,可以确定表信息。
2.FFF:第7到9位表示相对表空间的数据文件号。
3.BBBBBB:第10到15位表示这条记录在数据文件中的第几个BLOCK中。
4.RRR:最后3位表示这条记录是BLOCK中的第几条记录


  一个数据块坏了,那么这个数据块里的资料全部都不能读了
  因为读取数据的最小单位是block 所以应该是这个BLOCK中第0条记录开始



FUNCTION ROWID_CREATE RETURNS ROWID
参数名称                       类型                    输入/输出默认值?
------------------------------ ----------------------- ------ --------
ROWID_TYPE                     NUMBER                  IN
OBJECT_NUMBER                  NUMBER                  IN
RELATIVE_FNO                   NUMBER                  IN
BLOCK_NUMBER                   NUMBER                  IN
ROW_NUMBER                     NUMBER                  IN

如果对ROWID的结构不是很清楚 可以参考这个 http://blog.itpub.net/post/468/11046



(3) 建一个临时表 保存未损坏的资料



CREATE TABLE alantest.test_alan_bak AS SELECT * FROM alantest.test_alan Where 1=2;

SQL> INSERT INTO alantest.test_alan_bak SELECT /*+ ROWID(A) */ * FROM alantest.t
est_alan A WHERE rowid < 'AAABnjAAHAAAAAMAAA';

已创建0行。

SQL> INSERT INTO alantest.test_alan_bak SELECT /*+ ROWID(A) */ * FROM alantest.t
est_alan A WHERE rowid >= 'AAABnjAAHAAAAANAAA';

已创建6281行。



(4) 更改表名

    SQL>alter table alantest.test_alan rename to alantest.test_alan_0607;

    SQL>alter table alantest.test_alan_bak rename to alantest.test_alan;


(5) 根据临时表中的数据重构表 重建表上的索引 限制


D.  使用10231诊断事件 在做全表扫描的时候跳过坏块



步骤:

(1) 设置参数

    可以在session级别设定:

    SQL> ALTER SESSION SET EVENTS '10231 TRACE NAME CONTEXT FOREVER, LEVEL 10';

    会话已更改。

    也可以在数据库级别上设定 在初始化参数中加入

    event="10231 trace name context forever, level 10" 然后重启数据库
    或者
    ALter system set event '10231 TRACE NAME CONTEXT FOREVER, LEVEL 10';

(2) 创建一个临时表tmp_table把原始表中除坏块以外的资料都检索出来

    SQL> CREATE TABLE alantest.tmp_table as select * from alantest.test_alan;

    表已创建。

    SQL> select count(*) from alantest.test_alan;

    COUNT(*)
    ----------
      6281

(3) 更改表名

    SQL>alter table alantest.test_alan rename to alantest.test_alan_0607;

    SQL>alter table alantest.tmp_table rename to alantest.test_alan;

(4) 在新source_table上重新创建索引 约束 授权 trigger等对象

(5) 利用表之间的业务关系 把坏块中的数据补足


E.  使用dbms_repair包标记有坏块的表 在做全表扫描的时候跳过坏块



(1) 执行以下的语句:

    SQL> connect / as sysdba
    已连接。
    SQL> Execute DBMS_REPAIR.SKIP_CORRUPT_BLOCKS('ALANTEST','TEST_ALAN');

    PL/SQL 过程已成功完成。

  
    PROCEDURE SKIP_CORRUPT_BLOCKS
    参数名称                       类型                    输入/输出默认值?
    ------------------------------ ----------------------- ------ --------
    SCHEMA_NAME                    VARCHAR2                IN
    OBJECT_NAME                    VARCHAR2                IN
    OBJECT_TYPE                    BINARY_INTEGER          IN     DEFAULT
    FLAGS                          BINARY_INTEGER          IN     DEFAULT



(2) 使用exp工具或者create table as select的方法取出没有坏块数据

    SQL> create table alantest.aaa as select * from alantest.test_alan;

    表已创建。

    SQL> select count(*) from alantest.aaa;

    COUNT(*)
    ----------
      6281

(3) 重建表 表上的索引 约束 授权 trigger等对象


6. 如何检查数据库中是否存在坏块



1. ANALYZE TABLE tablename VALIDATE STRUCTURE CASCADE 同时校验表与索引

   它执行坏块的检查但是不会标记坏块为corrupt 检测的结果保存在USER_DUMP_DEST目录下的用户trace文件中



2. 使用RMAN

   RMAN> connect target /

   连接到目标数据库: ALAN (DBID=1282599050)

   RMAN> backup validate datafile 7;

   启动 backup 于 07-7月 -06
   正在使用目标数据库控制文件替代恢复目录
   分配的通道: ORA_DISK_1
   通道 ORA_DISK_1: sid=18 devtype=DISK
   通道 ORA_DISK_1: 正在激活 full 数据文件备份集
   通道 ORA_DISK_1: 正在指定备份集中的数据文件
   输入数据文件 fno=00007 name=D:\ORACLE\ORADATA\ALAN\TEST.ORA
   通道 ORA_DISK_1: 备份集已完成, 经过时间:00:00:04
   完成 backup 于 07-7月 -06

   检查alert.log

   ***
   Corrupt block relative dba: 0x01c0000c (file 7, block 12)
   Bad check value found during backing up datafile
   Data in bad block -
   type: 6 format: 2 rdba: 0x01c0000c
   last change scn: 0x0000.0007bc14 seq: 0x1 flg: 0x04
   consistency value in tail: 0xbc140601
   check value in block header: 0x91ea, computed block checksum: 0x110e
   spare1: 0x0, spare2: 0x0, spare3: 0x0
   ***
   Reread of blocknum=12, file=D:\ORACLE\ORADATA\ALAN\TEST.ORA. found same corrupt data

   查询v$database_block_corruption视图
 
   SQL> select * from v$database_block_corruption where file#=7;

     FILE#     BLOCK#     BLOCKS CORRUPTION_CHANGE# CORRUPTIO
    ---------- ---------- ---------- ------------------ ---------
         7         12          1                  0 FRACTURED

分享到:
评论

相关推荐

    数据库坏块(ORA-01578)的解决方法.pdf

    在 Oracle 数据库中,坏块错误(ORA-01578)是一种常见的故障,会导致数据库不可用,影响业务运营。本文将详细介绍坏块错误的解决方法,包括错误陷阱设置法和ROWID检测法,并提供了具体的命令和提示信息,对于数据库...

    oracle坏块处理

    ### Oracle坏块处理详解 #### 引言 在Oracle数据库管理中,遇到ORA-01578错误,即“Oracle数据块损坏”,是DBA(数据库管理员)们经常面临的一项挑战。这种错误通常伴随着ORA-01110错误,指向特定的数据文件及其...

    ora 错误全集 全部 ora0000-ora32999

    ORA-14400是索引块损坏,可能需要使用RMAN或DB_REPAIR坏块修复工具。 ORA-20000到ORA-29999主要涵盖PL/SQL(Procedural Language/SQL)和存储过程中的错误,例如ORA-24374表示定义的作业类型与实际的作业类型不匹配...

    断电与ORA-600问题集

    在某些特殊情况下,可能会出现ORA-600[4000]错误,此时应参照ORA-600[4000]的处理方法进行处理。 #### 1.4. 数据文件问题 ##### 1.4.1. 现象ORA-600[4000] ORA-600[4000]错误通常发生在数据文件损坏时,这可能是...

    Oracle 坏块修复

    "Oracle 坏块修复" Oracle 坏块修复是指在 Oracle 数据库中出现的数据块...坏块修复是 Oracle 数据库管理员需要掌握的重要技能,了解坏块的产生原因、预防措施和故障识别方法,对数据库的可用性和稳定性至关重要。

    Oracle坏块故障葵花宝典.docx

    由于应用软件可以正常使用,但偶尔会报错 ORA-01578,推断为索引上有坏块。 为了解决这个问题,我们使用以下步骤: 1. 登录数据库,检查错误日志,找到坏块的位置。 2. 使用 SQL 语句检查索引的完整性,发现索引...

    oracle报错(ORA-00600)问题处理

    Oracle数据库在运行过程中可能会遇到各种错误,其中ORA-00600是一个内部错误代码,表示遇到了数据库系统内部无法处理的异常情况。这个错误通常与数据库的底层结构或数据不一致有关,它不是一个通用错误,而是针对...

    ORACLE数据库一次意外宕机的分析处理实记(ora-1578)[文].pdf

    "ORACLE数据库一次意外宕机的分析处理实记(ora-1578)" 在本文中,我们将讲述ORACLE数据库一次意外宕机的分析处理过程。该宕机事件发生在测试环境中的一台装有ORACLE数据库的AIX小机上,导致数据库宕机。我们将从...

    oracle ORA-01114、ORA-27067错误解决方法

    Oracle数据库在运行过程中可能会遇到各种错误,其中"ORA-01114"和"ORA-27067"是两个常见的I/O错误,通常与数据文件的读写操作有关。这两个错误在本文中被提及,它们通常一起出现,并且可能伴随着其他如"OSD-04026"等...

    oracle数据库操作常见错误以及解决方案

    最后,错误`ORA-1652: unable to extend temp segment by 207381 in tablespace TEMPSPACE`和`ORA-01578: Oracle data block corrupted(file # num,block # num)`提示数据块损坏。这可能是由硬件、操作系统、内存、...

    ORACLE错误一览表.

    ### ORACLE错误一览表知识点详解 #### 一、会话管理相关错误 ##### ORA-00001: 违反唯一约束条件 - **描述**:当尝试插入重复的唯一键值到一个定义了唯一约束的列时触发。 - **解决方法**: - 检查并修改待插入的...

    oracle坏块处理方法[归类].pdf

    Oracle 坏块处理方法 Oracle 数据库在进行 SUN CLUSTER 双机切换、意外断电或其它情况下,有时会发生共享盘 MOUNT 不上的情况,需要使用 FSCK 对共享盘进行修复。修复完成后,在数据库启动过程中,却又出现 " 数据...

    BLOG_Oracle_lhr_【BBED】BBED模拟并修复ORA-08102错误

    通过本文的学习,读者将掌握使用BBED修复ORA-08102错误的方法,了解BBED的基本使用,能够解释数据块格式的dump文件,解读ORA-08102错误的trace文件,以及从rdba获取ROWID信息等实用技能。这些知识对于Oracle数据库...

    oracle介质恢复的内部过程

    Oracle介质恢复是数据库管理中的一个重要环节,尤其是在处理数据丢失或损坏的情况下。本文将详细探讨Oracle介质恢复的内部过程,通过对控制文件(controlfile)、重做日志(redolog)、数据文件(datafile)等内容的深入...

    oracle11g 内部参数出错问题

    Oracle 11g 内部错误代码 ORA-00600 是一个非常通用的错误,它表示数据库遇到了一个无法处理的内部错误或异常情况。这个错误通常涉及到Oracle数据库的底层结构,如数据块、索引或者内存管理等,且参数列表可以提供...

Global site tag (gtag.js) - Google Analytics