Oracle - 坏块修复

Posted 我的网络记事本

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 - 坏块修复的主要内容,如果未能解决你的问题,请参考以下文章

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

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

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

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

使用 DBMS_REPAIR 修复坏块

12 oracle 数据库坏块--物理坏块-ORA-01578/ORA-01110