現象:
在表上面新建主鍵報
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行:
- BBED> p *kdbr[12]
rowdata[0]----------ub1 rowdata[0] @1207 0x2c
格式化顯示:
- 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 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.