oracle 索引修复 Oracle索引重建

当数据库出现坏块而坏块所涉及对象为索引时,我们一般进行修复索引的方法是重建索引。
相对其它坏块,索引坏块修复起来最容易的。不过在修复前,我们需要确认这个坏块确实来自于某索引。

因此,这里我们会介绍一些块定位方法:

1. 如何在ORA-1578/RMAN/DBVERIFY的日志记录中确认讹误受损对象

首先需要确认绝对文件号(Absolute File Number: AFN)和块号(Block Number: BL)
 
绝对文件号(AFN)和相对文件号(RFN)经常相同,但也有时候不同。特别当:

  • 数据库是从Oracle7迁移而来
  • 或是使用了可传输表空间(Transportable/Plugged Tablespace)时
  • 或是配置的12c多租户
  • 或使用的bigfile表空间

提示的编号总是相对文件号(RFN)。

因此获取正确的AFN和RFN并分清含义可以节约你判断问题和定位的时间。


从ORA-1578报错中找到AFN

这里AFN是由ORA-1110报错提供的,并紧跟在ORA-1578之后。在下面例子中AFN为5,BL为34。

SQL> select * from scott.dept_view;
select * from scott.dept_view
*
ERROR at line 1:
ORA-01578: ORACLE data block corrupted (file # 11, block # 34)
ORA-01110: data file 5: '/home/oracle/oradata/users.dbf'

从DBVERIFY输出中找到AFN
在dbverify中坏块的定位描述会有些不同。DBVERIFY一般提供受到影响的RDBA地址。其中可以提取RFN并用于从dba_data_files表中查询到AFN。

  • 看下面例子(RFN=11 BL=34):
Page 34 is marked corrupt
Corrupt block relative dba: 0x02c00022 (file 11, block 34)
Bad check value found during dbv:
Data in bad block:
   type: 6 format: 2 rdba: 0x02c00022
   last change scn: 0x0771.4eebe71c seq: 0x2 flg: 0x04
   spare1: 0x0 spare2: 0x0 spare3: 0x0
   consistency value in tail: 0xe71c0602
   check value in block header: 0xd3ce
   computed block checksum: 0x2

Dbverify会在输出中显示相对数据块地址(rdba/dba)。上例从“Corrupt block relative dba: 0x02c00022 (file 11, block 34)”中可知rdba HEX值为0x02c00022。
这个实际上就提供了RFN和BL。当然这里之后也直接告诉你了“(file 11, block 34)”。
我们就可以从dba_data_files表中查到AFN。

  • 再看另一个例子(RFN=11 BL=35):
Dbv output:

DBV-200: Block, dba 46137379, already marked corrupted"

需要使用查询来先获取RFN和块号:

select dbms_utility.data_block_address_file(&&rdba) RFN,
       dbms_utility.data_block_address_block(&&rdba) BL
from dual;

可知:

SQL> select dbms_utility.data_block_address_file(&&rdba) RFN,
   2 dbms_utility.data_block_address_block(&&rdba) BL
   3 from dual;
Enter value for rdba: 46137379


RFN        BL
---------- ----------
11         35

通过RFN从dba_data_files获知AFN:

select file_id AFN, relative_fno, tablespace_name
from dba_data_files
where relative_fno=&RFN;

可知:

SQL> select file_id AFN, relative_fno, tablespace_name
   2 from dba_data_files
   3 where relative_fno=&RFN;
Enter value for rfn: 11

AFN        RELATIVE_FNO TABLESPACE_NAME
---------- ------------ ------------------------------
5          11           USERS

AFN是5。

从RMAN中获取AFN

在v$database_block_corruption中我们可以看到RMAN报告的讹误块信息。

FILE#列给出了AFN. BLOCK#列则是BL.


定位讹误对象
一旦我们取得了AFN,就可以用以下查询来定位讹误对象了:

select * 
from dba_extents
where file_id = &AFN
and &BL between block_id AND block_id + blocks - 1;

如:

SQL> select *
2 from dba_extents
3 where file_id = &AFN
4 and &BL between block_id AND block_id + blocks - 1;
Enter value for afn: 5
Enter value for bl: 34

OWNER SEGMENT_NAME PARTITION_NAME SEGMENT_TYPE TABLESPACE_NAME EXTENT_ID FILE_ID BLOCK_ID BYTES      BLOCKS RELATIVE_FNO
----- ------------ -------------- ------------ --------------- --------- ------- -------- ---------- ------ ------------
SCOTT DEPT                        TABLE        USERS           0         5       33       65536      8      11

如果出现上面的查询未返回行,那么可能坏块出现在本地表空间管理(Locally Managed Tablespace:LMT)下的段头上。
坏块出现在段头上,那么上面的查询不会返回结果,但是其会在alert日志中生产坏块报错信息。在这种情况下,你可以执行以下查询:

select owner, segment_name, segment_type, partition_name 
from   dba_segments
where  header_file = &AFN
  and  header_block = &BL;

如果坏块在空的EXTENT上(和某个对象无关),或者是在临时表上,上面的查询也会无返回。
对于临时表,Segment Type应该是TEMPORARY。

如果坏块在空的EXTENT上,那信息应该在DBA_FREE_SPACE上:

select * 
from  dba_free_space
where file_id = &AFN
  and &BL between block_id AND block_id + blocks - 1;

可以注意到在Oracle 10g和更高版本中的ORA-1578报错,alert日志中已经有指出讹误对象的相关信息了。如:

Corrupt Block Found
TSN = 5, TSNAME = USERS
RFN = 11, BLK = 34, RDBA = 46137378
OBJN = 46107, OBJD = 36440, OBJECT = DEPT, SUBOBJECT =
SEGMENT OWNER = SCOTT, SEGMENT TYPE = Table Segment

2. 如何在ORA-600 [6200] 报错中定位讹误的索引

描述:
在访问某张表时,你遇到ORA-600 [6200]报错,这个报错意味着相关索引被探测到存在讹误。
标准的解决方法是drop掉索引并为这张表重建所有相关索引。
不过,我们可以从trace文件当时生成的报错中定位哪个索引出的问题。
 
例如:

例子中显示的是从trace文件中看到的索引报错信息。

  • trace file报错信息:
  ksedmp: internal or fatal error
  ORA-00600: internal error code, arguments: [6200], [260], [262], [], [], [], [], []

  Block header dump: dba: 0x7b404757
   Object id on Block? Y
   seg/obj: 0x6190 csc: 0x00.4e537b5  itc: 2  flg: -typ: 2 - INDEX
       fsl: 0  fnx: 0x0 
  • 注意这里seg/obj指出的Hex值,我们可以将其转为十进制值,这个值就是对象id号。

    0x6190 也就是24976   Hex = 00006190  Octal = 00000060620

  • 这样我们就能在DBA_OBJECTS视图中找到索引对象了.
SVRMGR> SELECT OBJECT_ID, OBJECT_NAME FROM DBA_OBJECTS
          WHERE DATA_OBJECT_ID  = '24976';

DATA_OBJEC OBJECT_NAME                                                                 
---------- ------------------------------------------------------
     24976 tab1_index5

 这个索引就是我们应该去重建的那个。

重建索引语法

ALTER INDEX [schema.]index REBUILD  
     [PARAMETERS ('rebuild_params [physical_storage_params]' ) ] 
     [{ NOPARALLEL | PARALLEL [ integer ] }] ;
或

ALTER INDEX [schema.]index REBUILD ONLINE 
     [PARAMETERS ('rebuild_params [physical_storage_params]' ) ] 
     [{ NOPARALLEL | PARALLEL [ integer ] }] ;
或

ALTER INDEX [schema.]index REBUILD PARTITION partition  
     [PARAMETERS ('rebuild_params [physical_storage_params]' ) ];

需要注意的部分参数使用     
rebuild_params:

  • index_status=cleanup
    在进行online rebuild操作(ALTER INDEX REBUILD ONLINE)后,对相关表的旧版本索引(用户查询已经结束)进行清理。 

如:

ALTER INDEX [schema.]index REBUILD ONLINE PARAMETERS ('index_status=cleanup');

physical_storage_params:

  • tablespace
    指定索引建立在哪个表空间下。语法上和CREATE TABLE 所使用的指定TABLESPACE的STORAGE语法相同。
  • { NOPARALLEL | PARALLEL [ integer ] }
    默认为NOPARALLEL

如:

ALTER INDEX oldindex REBUILD PARAMETERS('tablespace=TBS_3');

猜你喜欢

转载自blog.csdn.net/liu_maclean/article/details/81711361
今日推荐