现象:
在表上面新建主键报
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.