ORA-08102異常重現及恢復

現象:

在表上面新建主鍵報 ORA-08102的異常:
    
    
    
    
SQL> alter table t add primary key(id);alter table t add primary key(id)*ERROR at line 1:ORA-00604: error occurred at recursive SQL level 1ORA-08102: index key not found, obj# 52, file 1, block 72661 (2)

重現異常:

一、查看基表CON$的_NEXT_CONSTRAINT信息和數據塊:
   
   
   
   
SQL> SELECT OWNER#,NAME,CON# FROM CON$ WHERE NAME='_NEXT_CONSTRAINT'; OWNER# NAME CON#---------- ------------------------------ ---------- 0 _NEXT_CONSTRAINT 11222

   
   
   
   
SQL> set lines 200SELECT OWNER#,NAME,CON#, dbms_rowid.ROWID_RELATIVE_FNO(rowid) fno, dbms_rowid.ROWID_BLOCK_NUMBER(rowid) bno, dbms_rowid.ROWID_ROW_NUMBER(rowid) rno FROM CON$ WHERE NAME='_NEXT_CONSTRAINT'; OWNER# NAME CON# FNO BNO RNO---------- ------------------------------ ---------- ---------- ---------- ---------- 0 _NEXT_CONSTRAINT 11222 1 289 12

記錄存儲在1號文件、289號block、第12行。

二、使用BBED查看數據塊

選擇1號文件第289號block:
   
   
   
   
[oracle@cqfrog bbed]$ bbed parfile=par.txt BBED> set file 1 block 289 FILE# 1 BLOCK# 289

打印第12行:
   
   
   
   
  1. BBED> p *kdbr[12]
rowdata[0]----------ub1 rowdata[0] @1207 0x2c

格式化顯示:
   
   
   
   
  1. BBED> x /rccnn
rowdata[0] @1207 ----------flag@1207: 0x2c (KDRHFL, KDRHFF, KDRHFH)lock@1208: 0x02cols@1209: 4col 0[1] @1210: .col 1[16] @1212: _NEXT_CONSTRAINTcol 2[4] @1229: 11222 col 3[1] @1234: 0

將offset爲1229的信息dump:
   
   
   
   
BBED> dump /v offset 1229 count 16 File: /u01/app/oracle/oradata/orcl/system01.dbf (1) Block: 289 Offsets: 1229 to 1244 Dba:0x00400121------------------------------------------------------- 04c3020d 1701802c 00040180 105f4e45 l .......,....._NE <16 bytes per line>

查看11222的16進制:
   
   
   
   
SQL> select dump(11222, 16) from dual;DUMP(11222,16)----------------------Typ=2 Len=4: c3,2,d,17
這裏的c3,2,d,17對應dump出來的信息: c3020d 17

三、關閉數據庫
必須先關閉數據庫, 不然修改不生效。
   
   
   
   
SQL> shutdown immediateDatabase closed.Database dismounted.ORACLE instance shut down.SQL> exitDisconnected from Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit ProductionWith the Partitioning, OLAP, Data Mining and Real Application Testing options

四、修改數據塊的值
使用bbed 修改數據塊的值 , 將11222 改大。

移動4位, 或者使用dump /v offset 1233count 16
    
    
    
    
BBED> dump /v offset +4 File: /u01/app/oracle/oradata/orcl/system01.dbf (1) Block: 289 Offsets: 1233 to 1248 Dba:0x00400121------------------------------------------------------- 1701802c 00040180 105f4e45 58545f43 l ...,....._NEXT_C <16 bytes per line>

將17修改成19:
   
   
   
   
BBED> modify /x 1901802c File: /u01/app/oracle/oradata/orcl/system01.dbf (1) Block: 289 Offsets: 1233 to 1248 Dba:0x00400121------------------------------------------------------------------------ 1901802c 00040180 105f4e45 58545f43 <32 bytes per line>BBED> sum applyCheck value for File 1, Block 289:current = 0x7fca, required = 0x7fcaBBED> dump /v offset 1233 File: /u01/app/oracle/oradata/orcl/system01.dbf (1) Block: 289 Offsets: 1233 to 1248 Dba:0x00400121------------------------------------------------------- 1901802c 00040180 105f4e45 58545f43 l ...,....._NEXT_C <16 bytes per line>

五、啓動數據庫
   
   
   
   
SQL> startupORACLE instance started.Total System Global Area 835104768 bytesFixed Size 2217952 bytesVariable Size 549455904 bytesDatabase Buffers 276824064 bytesRedo Buffers 6606848 bytesDatabase mounted.Database opened.


六、查看con$表的信息

使用全表掃描方式:
   
   
   
   
SQL> select /*+ FULL(t1) */ name,con# from con$ t1 where name='_NEXT_CONSTRAINT';NAME CON#------------------------------ ----------_NEXT_CONSTRAINT 11224

使用索引方式:
   
   
   
   
SQL> select /*+ index(t1 I_CON2) */ name,con# from con$ t1 where name='_NEXT_CONSTRAINT';NAME CON#------------------------------ ----------_NEXT_CONSTRAINT 11222


使用全表掃描和使用索引方式的值相差2。

七、新建測試表並增長主鍵

   
   
   
   
SQL> create table t as select * from test where rownum<10;Table created.SQL> desc t; Name Null? Type ----------------------------------------- -------- ---------------------------- ID NUMBER NAME VARCHAR2(128


   
   
   
   
SQL> alter table t add primary key(id);alter table t add primary key(id)*ERROR at line 1:ORA-00604: error occurred at recursive SQL level 1ORA-08102: index key not found, obj# 52, file 1, block 72661 (2)

觀察發現, 有ORA-8102異常。


修復ORA-08102異常:

一、根據報錯信息定位數據塊
   
   
   
   
SQL> alter table t add primary key(id);alter table t add primary key(id)*ERROR at line 1:ORA-00604: error occurred at recursive SQL level 1ORA-08102: index key not found, obj# 52, file 1, block 72661 (2)

位置:file 1, block 72661

二、查看索引和全表掃描的信息
    
    
    
    
SQL> select /*+ FULL(t1) */ name,con# from con$ t1 where name='_NEXT_CONSTRAINT';NAME CON#------------------------------ ----------_NEXT_CONSTRAINT 11224SQL> select /*+ index(t1 I_CON2) */ name,con# from con$ t1 where name='_NEXT_CONSTRAINT';NAME CON#------------------------------ ----------_NEXT_CONSTRAINT 11222


三、dump報錯的數據塊

根據alert日誌或者dump數據塊:

    
    
    
    
  1. 1 Default Trace File /u01/app/oracle/diag/rdbms/orcl/orcl/trace/orcl_ora_6051.trc
SQL> alter system dump datafile 1 block 72661;System altered.SQL> select * from v$diag_info;

在dump文件搜索8102錯誤:
 能夠看到數據塊指望的值是:c3 02 0d 19 。11224。
     
     
     
     
SQL> select UTL_RAW.CAST_TO_NUMBER(replace('c3 02 0d 19',' ','')) from dual;UTL_RAW.CAST_TO_NUMBER(REPLACE('C3020D19','',''))------------------------------------------------- 11224


查看dump的文件:
    
    
    
    
row#198[3566] flag: ---D--, lock: 2, len=13, data:(6): 00 41 38 6c 00 adcol 0; len 4; (4): c3 02 0d 15row#199[3540] flag: ---D--, lock: 2, len=13, data:(6): 00 41 38 6c 00 afcol 0; len 4; (4): c3 02 0d 16row#200[3553] flag: ------, lock: 0, len=13, data:(6): 00 40 01 21 00 0ccol 0; len 4; (4): c3 02 0d 17----- end of leaf block dump -----End dump data blocks tsn: 0 file#: 1 minblk 72661 maxblk 72661

找到最後, 圖上的紅色部分:
00 40 01 21 00 0c 是rowid信息:
文件號: 00 40  (取前十位,1)
塊號:     01 21   (289)
行號:     00 0c   (12)

注意:這裏dump的索引的塊, 能夠看到對應的數據塊的rowid。
咱們使用bbed能夠看到文件一、數據塊28九、12行的數據是多少, 這裏省略了。
咱們看到索引存儲的值爲: c3 02 0d 17 轉換爲10進製爲11222。
   
   
   
   
SQL> select UTL_RAW.CAST_TO_NUMBER(replace('c3 02 0d 17',' ','')) from dual;UTL_RAW.CAST_TO_NUMBER(REPLACE('C3020D17','',''))------------------------------------------------- 11222
從前面的全表掃描的結果, 指望值應該爲11224, 所以只須要將索引塊值修改成 c3 02 0d 19。 便可與數據塊保持一致。



四、使用BBED修復

查找offset的值:
查看dump的信息, 索引塊的ITL槽位有3個, 能夠計算offset以下:
offset =  3553+44+8+24*ITL_CNT
= 3553+44+8+24*3= 3677

指定文件和塊:
   
   
   
   
BBED> set file 1 block 72661; FILE# 1 BLOCK# 72661

定位到行:
   
   
   
   
BBED> dump offset 3677 count 16 File: /u01/app/oracle/oradata/orcl/system01.dbf (1) Block: 72661 Offsets: 3677 to 3692 Dba:0x00411bd5------------------------------------------------------------------------ 04c3020d 17010200 41386c00 ad04c302

修改:
   
   
   
   
BBED> modify /x 19 offset 3681 File: /u01/app/oracle/oradata/orcl/system01.dbf (1) Block: 72661 Offsets: 3681 to 3696 Dba:0x00411bd5------------------------------------------------------------------------ 19010200 41386c00 ad04c302 0d150100 <32 bytes per line>BBED> sum applyCheck value for File 1, Block 72661:current = 0x1fa3, required = 0x1fa3BBED> dump offset 3677 count 16 File: /u01/app/oracle/oradata/orcl/system01.dbf (1) Block: 72661 Offsets: 3677 to 3692 Dba:0x00411bd5------------------------------------------------------------------------ 04c3020d 19010200 41386c00 ad04c302 <32 bytes per line>

五、打開數據庫驗證

查看全表掃描和索引掃描的值是否一致:
   
   
   
   
SQL> select /*+ FULL(t1) */ name,con# from con$ t1 where name='_NEXT_CONSTRAINT';NAME CON#------------------------------ ----------_NEXT_CONSTRAINT 11224SQL> select /*+ index(t1 I_CON2) */ name,con# from con$ t1 where name='_NEXT_CONSTRAINT';NAME CON#------------------------------ ----------_NEXT_CONSTRAINT 11224

驗證增長主鍵能成功:
   
   
   
   
SQL> alter table t add primary key(id);Table altered.
相關文章
相關標籤/搜索