当数据库出现坏块而坏块所涉及对象为索引时,我们一般进行修复索引的方法是重建索引。
相对其它坏块,索引坏块修复起来最容易的。不过在修复前,我们需要确认这个坏块确实来自于某索引。
因此,这里我们会介绍一些块定位方法:
1. 如何在ORA-1578/RMAN/DBVERIFY的日志记录中确认讹误受损对象
首先需要确认绝对文件号(Absolute File Number: AFN)和块号(Block Number: BL)
绝对文件号(AFN)和相对文件号(RFN)经常相同,但也有时候不同。特别当:
提示的编号总是相对文件号(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。
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。
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文件中看到的索引报错信息。
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
0x6190 也就是24976 Hex = 00006190 Octal = 00000060620
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:
如:
ALTER INDEX [schema.]index REBUILD ONLINE PARAMETERS ('index_status=cleanup');
physical_storage_params:
如:
ALTER INDEX oldindex REBUILD PARAMETERS('tablespace=TBS_3');