怎么修复数据库 修复数据库坏块方法

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了怎么修复数据库 修复数据库坏块方法相关的知识,希望对你有一定的参考价值。

  修复数据库坏块
  dbv
  你也可以用dbv工具看一下你现在其他的数据文件有没有还有坏块的
  dbv file=\'yourfilename\'
  恢复方法:
  当Oracle数据库出现坏块时,Oracle会在警告日志文件(alert_SID.log)中记录坏块的信息:
  ORA-01578: ORACLE data block corrupted (file # 7, block # )
  ORA-01110: data file : \'/oracle1/oradata/V920/oradata/V816/users01.dbf\'
  其中,<AFN>代表坏块所在数据文件的绝对文件号,代表坏块是数据文件上的第几个数据块
  出现这种情况时,应该首先检查是否是硬件及操作系统上的故障导致Oracle数据库出现坏块。在排除了数据库以外的原因后,再对发生坏块的数据库对象进行处理。
  1.确定发生坏块的数据库对象
  SELECT tablespace_name,
  segment_type,
  owner,
  segment_name
  FROM dba_extents
  WHERE file_id =
  AND between block_id AND block_id+blocks-1;
  2.决定修复方法
  如果发生坏块的对象是一个索引,那么可以直接把索引DROP掉后,再根据表里的记录进行重建;
  如果发生坏块的表的记录可以根据其它表的记录生成的话,那么可以直接把这个表DROP掉后重建;
  如果有数据库的备份,则恢复数据库的方法来进行修复;
  如果表里的记录没有其它办法恢复,那么坏块上的记录就丢失了,只能把表中其它数据坏上的记录取出来,然后对这个表进行重建。
  3.用Oracle提供的DBMS_REPAIR包标记出坏块
  exec DBMS_REPAIR.SKIP_CORRUPT_BLOCKS(\'\',\'\');
  4.使用Create table as select命令将表中其它块上的记录保存到另一张表上
  create table corrupt_table_bak
  as
  select * from corrupt_table;
  5.用DROP TABLE命令删除有坏块的表
  drop table corrupt_table;
  6.用alter table rename命令恢复原来的表
  alter table corrupt_table_bak
  rename to corrupt_table;
  7.如果表上存在索引,则要重建表上的索引
  PART2
  2014.7.22研究恢复数据库坏块:
  Oracle调用标准C的系统函数,对数据块进行读写操作,因此,坏块是有可能由以下几种原因产生:
  硬件的I/O错误
  操作系统的I/O错误或缓冲问题
  内存或paging问题
  磁盘修复工具
  一个数据文件的一部分正在被覆盖
  Oracle试图访问一个未被格式化的系统块失败
  数据文件部分溢出
  Oracle或者操作系统的bug
  遇到“ORA-01578:ORACLE data block corrupted”错误
  处理方法:1.rman的recover命令可以在数据库保持open状态下只恢复受损的数据块
  2.如果没有备份,万不得已之下也可以采用DBMS_REPAIR包的存储过程将受损坏块隔离,同时尽可能地挽救部分数据。
  rman backup命令也是检查坏数据块的好工具 一旦读取ORA-19566 即可有问题
  此时可用backup validate tablespace user观察详细的信息,可查看到坏块数与跟踪文件
  grep‘corrupt’/u01/app/oracle/diag/rdbms/br/br/trace/**.trc
  恢复数据块:rman》recover datafile 5 block 203;
  批量恢复受损的数据块:recover corruption list;
  数据块坏块一号坏块,需要做:
  run
  sql \'alter database datafile 5 offline\';
  restore datafile 5;
  recover datafile 5;
  sql\'alter database datafile 5 online\'
  
  使用exp/imp恢复
  在这种情况下肯定会造成数据的丢失,在这种情况下应采取将数据导出然后重建表再进行导入的方法,来尽量恢复损坏数据块中的数据,但是在有坏块的情况下是不允许导出的,如下命令:Exp test/test file=t.dmp tables=t;
  导出命令在执行中会报ORA-01578错误,在这错误提示中会提示那个文件号的文件以及这个文件中的哪个块被损坏,如:ORA—01578:ORACLE 数据块损坏(文件号 4,块号 35)
  针对以上的提示首先查询那些对象被损坏:
  Select tablespace_name,segment_type,owner,segment_name From dba_extents Where file_id=4 and 35 between block_id and block_id+blocks-1;
  如果被损坏的块是索引,通常可以通过索引重建来解决,如果损坏的是数据(segment_type为table),那么通过设置如下内部事件使得Exp操作跳过坏块。
  Alter session set events=’10231 trace name context forever,level 10’;
  然后重新执行导出命令,导出相关的表,然后执行Drop Table命令删除相关表,之后重建表最后导入数据。
  使用DBMS_REPAIR恢复
  用DBMS_REPAIR当然也会丢失数据。这里不做详细的介绍,有兴趣的可以查看oracle的在线文
  3、使用dbms_repair包进行坏块处理
  1)首先建立repair_table,用于存放dbms_repair.check_object检测出来的坏块信息
  SQL> declare
  2begin
  3dbms_repair.admin_tables
  4(table_name => \'REPAIR_TABLE\',--表名
  5table_type => dbms_repair.repair_table,
  6action => dbms_repair.create_action,
  7tablespace => \'USERS\');--用于指定该表存放的表空间
  8end;
  9/
  PL/SQL 过程已成功完成。
  SQL> col owner format a10
  SQL> col object_name format a20
  SQL> col object_type format a20
  SQL> select owner, object_name, object_type
  2from dba_objects
  3where object_name like \'%REPAIR_TABLE\';
  OWNEROBJECT_NAMEOBJECT_TYPE
  ---------- -------------------- --------------------
  SYSREPAIR_TABLETABLE
  SYSDBA_REPAIR_TABLEVIEW
  Oracle自动创建了一个DBA_REPAIR_TABLE视图。
  2)使用dbms_repair.check_object进行坏块检测
  SQL> set serveroutput on size 100000;
  SQL> declare
  2rpr_count int;
  3begin
  4rpr_count := 0;
  5dbms_repair.check_object(
  6schema_name => \'SYS\',--指定对象模式,也就是对象的所有者
  7object_name => \'TEST\',--指定对象名,也就是表名
  8repair_table_name => \'REPAIR_TABLE\',
  9corrupt_count => rpr_count);
  10dbms_output.put_line(\'repair block count: \'
  11||to_char(rpr_count));
  12end;
  13/
  repair block count: 4
  PL/SQL 过程已成功完成。
  SQL> select object_name, block_id, corrupt_type, marked_corrupt,
  2corrupt_description, repair_description
  3from repair_table;
  OBJECT_NAMEBLOCK_ID CORRUPT_TYPE MARKED_COR
  -------------------- ---------- ------------ ----------
  CORRUPT_DESCRIPTION
  -------------------------------------------------------------------------------
  REPAIR_DESCRIPTION
  -------------------------------------------------------------------------------
  TEST196148 TRUE
  mark block software corrupt
  TEST206148 TRUE
  mark block software corrupt
  TEST236148 TRUE
  mark block software corrupt
  TEST316148 TRUE
  mark block software corrupt
  通过运行dbms_repair.check_object,将坏块信息存放到了repair_table表中,其中有个字段marked_corrupt,用于标识该块是否被标识为坏块,当被标识为true时,即该块被标识为坏块。其中这一步跟oracle文档中的描述有点进入,根据oracle文档,当执行完dbms_repair.check_object时,并不会进行坏块标识,也就是marked_corrupt列的值应该为false,而只有当执行dbms_repair.fix_corrupt_blocks过程后才会进行坏块标识。
  3)使用dbms_repair.fix_corrupt_blocks进行坏块标识
  SQL> declare
  2fix_block_count int;
  3begin
  4fix_block_count := 0;
  5dbms_repair.fix_corrupt_blocks (
  6schema_name => \'SYS\',
  7object_name => \'TEST\',
  8object_type => dbms_repair.table_object,
  9repair_table_name => \'REPAIR_TABLE\',
  10fix_count => fix_block_count);
  11dbms_output.put_line(\'fix blocks count: \' ||
  12to_char(fix_block_count));
  13end;
  14/
  fix blocks count: 0
  PL/SQL 过程已成功完成。
  我们可以见到到fix blocks count=0,即在上一步进行check_object时已经进行了坏块标识了,这一步其实可以省略。(不过没有测试过!)
 
参考技术A Oracle DBA神器:PRM-DUL灾难恢复工具,Schema级别数据恢复。PRM-DULFor Oracle Database – schema级别oracle数据库数据恢复特性 ,PRM-DUL即ParnassusData Recovery Manager是企业级别Oracle数据库灾难恢复工具。PRM可以在无备份的情况下恢复被truncated掉的表,也可以恢复无法打开的Oracle数据库(Alter Database Open失败)中的数据。

Oracle - 坏块修复

一、概述

本文将介绍如何模拟坏块,以及出现坏块该如何修复。实验分为以下几个步骤。
1. 表出现坏块
2. 索引出现坏块


二、环境准备

本实验都是在oracle 11G归档模式下进行。


1. 准备相关表

create tablespace tbs01 datafile ‘/u01/app/oracle/oradata/orcltest/tbs01.dbf‘ size 100m;
create table scott.t01 tablespace tbs01 as select * from dba_objects where rownum<=100;
create index scott.idx_t01 on scott.t01(object_id) tablespace tbs01;

select rowid, dbms_rowid.rowid_relative_fno(rowid) file_id, dbms_rowid.rowid_block_number(rowid) block_id from scott.t01;

ROWID                 FILE_ID   BLOCK_ID
------------------ ---------- ----------
AAAVpMAAGAAAACDAAA          6        131
AAAVpMAAGAAAACDAAB          6        131
AAAVpMAAGAAAACDAAC          6        131
AAAVpMAAGAAAACDAAD          6        131
AAAVpMAAGAAAACDAAE          6        131
AAAVpMAAGAAAACDAAF          6        131
AAAVpMAAGAAAACDAAG          6        131
...

select segment_name, segment_type, file_id, block_id, blocks from dba_extents where segment_name=‘IDX_T01‘;

SEGMENT_NAME    SEGMENT_TYPE          FILE_ID   BLOCK_ID     BLOCKS
--------------- ------------------ ---------- ---------- ----------
IDX_T01         INDEX                       6        136          8


2. 全库备份

RMAN> backup database;  // 全库备份

RMAN> list backup;  // 查看备份

List of Backup Sets
===================
BS Key  Type LV Size       Device Type Elapsed Time Completion Time
------- ---- -- ---------- ----------- ------------ ---------------
19      Full    1.08G      DISK        00:01:59     12-MAR-20
        BP Key: 19   Status: AVAILABLE  Compressed: NO  Tag: TAG20200312T150629
        Piece Name: /home/oracle/backupdir/ORCLTEST_2750922031_40_1_20200312_1034867190.bkp
  List of Datafiles in backup set 19
  File LV Type Ckp SCN    Ckp Time  Name
  ---- -- ---- ---------- --------- ----
  1       Full 1148218    12-MAR-20 /u01/app/oracle/oradata/orcltest/system01.dbf
  2       Full 1148218    12-MAR-20 /u01/app/oracle/oradata/orcltest/sysaux01.dbf
  3       Full 1148218    12-MAR-20 /u01/app/oracle/oradata/orcltest/undotbs01.dbf
  4       Full 1148218    12-MAR-20 /u01/app/oracle/oradata/orcltest/users01.dbf
  5       Full 1148218    12-MAR-20 /u01/app/oracle/oradata/orcltest/example01.dbf
  6       Full 1148218    12-MAR-20 /u01/app/oracle/oradata/orcltest/tbs01.dbf


三、正式实验

1. 表出现坏块


1.1 模拟坏块
  RMAN> blockrecover datafile 6 block 131 clear;  // 将131数据块清空,即相当于产生了坏块 

SQL> select * from scott.t01;  // 对表进行查询

select * from scott.t01
                    *
ERROR at line 1:
ORA-01578: ORACLE data block corrupted (file # 6, block # 131)
ORA-01110: data file 6: ‘/u01/app/oracle/oradata/orcltest/tbs01.dbf‘


1.2 检测坏块

检测坏块可以使用以下两种方式


a. 使用rman检测坏块
RMAN> backup check logical validate datafile 6;

List of Datafiles
=================
File Status Marked Corrupt Empty Blocks Blocks Examined High SCN
---- ------ -------------- ------------ --------------- ----------
6    FAILED 0              12656        12800           1234072
  File Name: /u01/app/oracle/oradata/orcltest/tbs01.dbf
  Block Type Blocks Failing Blocks Processed
  ---------- -------------- ----------------
  Data       1              2
  Index      0              3
  Other      0              139

validate found one or more corrupt blocks

上面rman检测到的坏块具体信息可以通过v$database_block_corruption查看


b. 使用oracle安装时自带的dbv工具
[oracle@orasingle ~]$ dbv file=‘/u01/app/oracle/oradata/orcltest/tbs01.dbf‘

Total Pages Examined         : 12800
Total Pages Processed (Data) : 1
Total Pages Failing   (Data) : 0
Total Pages Processed (Index): 3
Total Pages Failing   (Index): 0
Total Pages Processed (Other): 139
Total Pages Processed (Seg)  : 0
Total Pages Failing   (Seg)  : 0
Total Pages Empty            : 12656
Total Pages Marked Corrupt   : 1
Total Pages Influx           : 1
Total Pages Encrypted        : 0
Highest block SCN            : 1234072 (0.1234072)
但是通过dbv工具并不能直观判断到底是什么类型数据块出现了坏块


1.3 坏块修复

RMAN> backup check logical validate datafile 6;  // 检测数据文件的坏块
RMAN> blockrecover corruption list;  // 自动修复检测出的坏块,该命令执行成功的前提是有完整的rman备份

SQL> select * from scott.t01;  // 再查询就没有错误了


2. 索引出现坏块

查看下面sql的执行计划
SQL> select * from scott.t01 where object_id=100;
SQL> select * from table(dbms_xplan.display_cursor(null,null,‘TYPICAL PEEKED_BINDS‘));

---------------------------------------------------------------------------------------
| Id  | Operation                   | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |         |       |       |     2 (100)|          |
|   1 |  TABLE ACCESS BY INDEX ROWID| T01     |     1 |   207 |     2   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | IDX_T01 |     1 |       |     1   (0)| 00:00:01 |
---------------------------------------------------------------------------------------


2.1 模拟坏块

RMAN> blockrecover datafile 6 block 139 clear;  // 将139索引块清空,即相当于索引产生了坏块 
可能大家会有疑惑,该索引的块的block_id是136,你为什么要清空139呢?这就涉及到段的管理方式了,136-138这三个块依次是一级位图块,二级位图块,段头。真正存放数据的是从139开始。可以将块dump出来看看块的类型。

SQL> select * from scott.t01 where object_id=100;  // 再来查询该sql

select * from scott.t01 where object_id=100
*
ERROR at line 1:
ORA-01578: ORACLE data block corrupted (file # 6, block # 139)
ORA-01110: data file 6: ‘/u01/app/oracle/oradata/orcltest/tbs01.dbf‘

在这里我们可以看到,这里的报错与前面表上有坏块的报错一模一样,因此当我们查询一张表出现这类报错的时候,可能并不是表有坏块,而可能是这张表上的索引有坏块。


2.2 检查坏块

RMAN> backup check logical validate datafile 6;

List of Datafiles
=================
File Status Marked Corrupt Empty Blocks Blocks Examined High SCN
---- ------ -------------- ------------ --------------- ----------
6    FAILED 0              12657        12800           1158959
  File Name: /u01/app/oracle/oradata/orcltest/tbs01.dbf
  Block Type Blocks Failing Blocks Processed
  ---------- -------------- ----------------
  Data       0              1
  Index      1              3
  Other      0              139

validate found one or more corrupt blocks

同样也可以通过下面的sql确定坏块的段类型。
select owner, segment_name, segment_type from dba_extents where 139 between block_id and block_id+blocks-1 and file_id=6;


2.3 修复坏块

索引的坏块修复有两种方式,第一种就是跟表一样,直接修复数据文件
RMAN> backup check logical validate datafile 6;  // 检测数据文件的坏块
RMAN> blockrecover corruption list;  // 自动修复检测出的坏块

第二种方式就是将索引直接删了重建,原理就是如果索引被删除了,这个段就会被系统回收,该段上所有的块都会被初始化,也就不存在什么坏块了。
select dbms_metadata.get_ddl(‘INDEX‘, ‘IDX_T01‘, ‘SCOTT‘) from dual;  // 通过该sql查索引的创建信息
drop index scott.idx_t01;  // 删除索引
CREATE INDEX "SCOTT"."IDX_T01" ON "SCOTT"."T01" ("OBJECT_ID") TABLESPACE "TBS01" online;  // 创建索引


2.4 试试rebuild online

可能你会问,为什么索引删了重建,直接rebuild不更好吗?那么我们再试试索引有坏块了,rebuild是个什么效果

RMAN> blockrecover datafile 6 block 139 clear;

RMAN> backup check logical validate datafile 6;

List of Datafiles
=================
File Status Marked Corrupt Empty Blocks Blocks Examined High SCN
---- ------ -------------- ------------ --------------- ----------
6    FAILED 0              12656        12800           1234071
  File Name: /u01/app/oracle/oradata/orcltest/tbs01.dbf
  Block Type Blocks Failing Blocks Processed
  ---------- -------------- ----------------
  Data       0              2
  Index      1              3
  Other      0              139


使用rebuild命令重建索引
alter index scott.idx_t01 rebuild online;

RMAN> backup check logical validate datafile 6;  // 可以看到坏块依然存在

List of Datafiles
=================
File Status Marked Corrupt Empty Blocks Blocks Examined High SCN
---- ------ -------------- ------------ --------------- ----------
6    FAILED 0              12656        12800           1237004
  File Name: /u01/app/oracle/oradata/orcltest/tbs01.dbf
  Block Type Blocks Failing Blocks Processed
  ---------- -------------- ----------------
  Data       0              2
  Index      1              3
  Other      0              139

select * from scott.t01 where object_id=100;  // 查询没有问题,索引也有效
select * from table(dbms_xplan.display_cursor(null,null,‘TYPICAL PEEKED_BINDS‘));
---------------------------------------------------------------------------------------
| Id  | Operation                   | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |         |       |       |     2 (100)|          |
|   1 |  TABLE ACCESS BY INDEX ROWID| T01     |     1 |   207 |     2   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | IDX_T01 |     1 |       |     1   (0)| 00:00:01 |
---------------------------------------------------------------------------------------

所以,如果是索引的坏块,不建议使用rebuild online,因为它虽然让索引能够正常使用,但是坏块依然存在。
 

四、总结

1. 坏块修复的前提是要有完整的备份,所以一定得为生产环境指定备份策略
2. 表的坏块恢复直接使用rman
3. 索引的坏块恢复可以使用rman,也可通过删除索引再重建的方式修复

如果该主库有dg,那么主库有坏块又该如何修复,dg有坏块又该如何修复,请看“dg坏块修复(二)”

以上是关于怎么修复数据库 修复数据库坏块方法的主要内容,如果未能解决你的问题,请参考以下文章

实战篇:Oracle 数据坏块的 N 种修复方式

实战篇:Oracle 数据坏块的 N 种修复方式

使用BBED修复Oracle坏块恢复方法

hadoop 之hdfs数据块修复方法

Oracle - 坏块修复

使用 DBMS_REPAIR 修复坏块