利用bbed来修复ora-08102错误

转载请注明出处:http://blog.csdn.net/guoyjoe/article/details/39677575

1、重现ORA-8102错主的实验步骤:

SQL> conn gyj/gyj
Connected.

SQL>  drop table gyj_1000;

Table dropped.

SQL> create table gyj_1000(id int,name varchar2(100));

Table created.

SQL> SQL> begin
  2      for i in 1 .. 5000 loop
  3       insert into gyj_1000 values(i,‘gyj‘||i);
  4        commit;
  5      end loop;
  6  end;
  7  /

SQL> select user_id,username from dba_users;

USER_ID USERNAME
---------- ------------------------------
         9 OUTLN
        32 GYJ
         0 SYS
         5 SYSTEM
        31 APPQOSSYS
        14 DIP
        30 DBSNMP
        21 ORACLE_OCM

8 rows selected.

SQL> alter table gyj_1000 add primary key(id);

Table altered.

SQL> select CONSTRAINT_NAME from dba_constraints where table_name=‘GYJ_1000‘;

CONSTRAINT_NAME
------------------------------
SYS_C003766

SQL> conn / as sysdba
Connected.
SQL> select name,con# from con$ where owner#=32;

NAME                                 CON#
------------------------------ ----------
SYS_C003767                          3767
BIN$Ayykzh6uGBfgUwEAAH9D0w==$0       3765
SYS_C003768                          3768

SQL> select name,con# from con$ where name=‘_NEXT_CONSTRAINT‘;

NAME                                 CON#
------------------------------ ----------
_NEXT_CONSTRAINT                     3769

SQL> select dbms_rowid.rowid_relative_fno(rowid) file#,dbms_rowid.rowid_block_number(rowid) block#,
  2   dbms_rowid.rowid_row_number(rowid) row#
  3   from con$
  4   where name=‘_NEXT_CONSTRAINT‘;

FILE#     BLOCK#       ROW#
---------- ---------- ----------
         1        289         12

[[email protected] ~]$ bbed parfile=par.txt
Password:

BBED: Release 2.0.0.0.0 - Limited Production on Tue Sep 16 17:52:09 2014

Copyright (c) 1982, 2011, Oracle and/or its affiliates.  All rights reserved.

************* !!! For Oracle Internal Use only !!! ***************

BBED> set file 1   block 289
        FILE#           1
        BLOCK#          289

BBED> p *kdbr[12]
rowdata[0]
----------
ub1 rowdata[0]                              @1220     0x2c

BBED> x /rccnn
rowdata[0]                                  @1220    
----------
[email protected]: 0x2c (KDRHFL, KDRHFF, KDRHFH)
[email protected]: 0x02
[email protected]:    4

col    0[1] @1223: .
col   1[16] @1225: _NEXT_CONSTRAINT
col    2[3] @1242: 3769
col    3[1] @1246: 0

BBED> d /v offset 1242 count 16
 File: /u01/app/oracle/oradata/jfdb/system01.dbf (1)
 Block: 289     Offsets: 1242 to 1257  Dba:0x00400121
-------------------------------------------------------
 03c22646 01802c00 04018010 5f4e4558 l .?&F..,....._NEX

<16 bytes per line>
SQL> select dump(3769,16) from dual;

DUMP(3769,16)
---------------------
Typ=2 Len=3: c2,26,46

我把值改小:45

BBED> modify /x 45 offset 1245
Warning: contents of previous BIFILE will be lost. Proceed? (Y/N) y
 File: /u01/app/oracle/oradata/jfdb/system01.dbf (1)
 Block: 289              Offsets: 1245 to 1260           Dba:0x00400121
------------------------------------------------------------------------
 4401802c 00040180 105f4e45 58545f43

<32 bytes per line>

BBED> sum apply
Check value for File 1, Block 289:
current = 0xa831, required = 0xa831

BBED> p *kdbr[12]
rowdata[0]
----------
ub1 rowdata[0]                              @1220     0x2c

BBED> x /rccnn
rowdata[0]                                  @1220    
----------
[email protected]: 0x2c (KDRHFL, KDRHFF, KDRHFH)
[email protected]: 0x02
[email protected]:    4

col    0[1] @1223: .
col   1[16] @1225: _NEXT_CONSTRAINT
col    2[3] @1242: 3768
col    3[1] @1246: 0

SQL> shutdown immediate;
Database closed.
Database dismounted.
ORACLE instance shut down.
SQL> startup
ORACLE instance started.

Total System Global Area 1570009088 bytes
Fixed Size                  2228704 bytes
Variable Size            1442844192 bytes
Database Buffers          117440512 bytes
Redo Buffers                7495680 bytes
Database mounted.
Database opened.

SQL>  alter table gyj_1000 drop primary key;

Table altered.

SQL> SQL> alter table gyj_1000 add primary key(id);

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

2、分析ORA-8102错误

alter table gyj_1000 add primary key(id);

ORA-8102常见于索引键值与表上存的值不一致。(Corruption related to Index 索引)

ORA-8102即可能是ORACLE的bug,也可能是由于硬件I/O错误所引起。硬件或者I/O子系统由于丢失写 Lost Write造成块的逻辑上讹误,当一个Lost Io发生,包含对key的修改或者没有写入到ORACLE数据文件上,这即可能发生在表块上也可能发生在索引块上。

查看这个对象号为52的对象,发现是 SYS.CON$ 表中 I_CON2索引 ,这是 一个 BOOTSTRP$ 对象,而且 OBJ# 为51 ,所以这是一个 核心BOOTSTRP$ 对象,是不能通过startup migrate 和 event 38003 重建的,所以最终只能通过BBED去修改这个块中有问题的地方。

先通过下面这个SQL,查找表和索引之间到底相差什么

SQL> conn / as sysdba
Connected.
SQL> SELECT /*+ FULL(t1) */
  2  owner#, NAME, con#
  3    FROM CON$ t1
  4  MINUS
  5  SELECT /*+ index(t I_CON2) */
  6  owner#, NAME, con#
  7    FROM CON$ t;

OWNER# NAME                                 CON#
---------- ------------------------------ ----------
         0 _NEXT_CONSTRAINT                     3776

SQL> select  /*+ FULL(t1) */ owner#,name,con# from con$ t1 WHERE NAME=‘_NEXT_CONSTRAINT‘;

OWNER# NAME                                 CON#
---------- ------------------------------ ----------
         0 _NEXT_CONSTRAINT                     3776

SQL> select  /*+ index(t1 I_CON2) */ owner#,name,con# from con$ t1 WHERE NAME=‘_NEXT_CONSTRAINT‘;

OWNER# NAME                                 CON#
---------- ------------------------------ ----------
         0 _NEXT_CONSTRAINT                     3775

利用这样的方法来查询表和索引之间的不一致 ,
通过查询结果 确实可以看到 表和索引存在不一样的,就是CON$表中有 CON#=3776的这一列,而索引的键值中却没有3776
(要知道索引的键值就是保存该索引对应的字段值啊)


3、此时已经出现了类似的不一致。通过trace文件发现con$表的数

[[email protected] ~]# cat  /u01/app/oracle/diag/rdbms/jfdb/jfdb/trace/alert_jfdb.log

[[email protected] ~]# vi /u01/app/oracle/diag/rdbms/jfdb/jfdb/trace/jfdb_ora_6518.trc

Trace file /u01/app/oracle/diag/rdbms/jfdb/jfdb/trace/jfdb_ora_6518.trc
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
ORACLE_HOME = /u01/app/oracle/product/11.2.0
System name:    Linux
Node name:      jfdb
Release:        2.6.18-128.el5
Version:        #1 SMP Wed Dec 17 11:41:38 EST 2008
Machine:        x86_64
VM name:        VMWare Version: 6
Instance name: jfdb
Redo thread mounted by this instance: 1
Oracle process number: 17
Unix process pid: 6518, image: [email protected] (TNS V1-V3)

*** 2014-09-16 18:10:13.477
*** SESSION ID:(1512.7) 2014-09-16 18:10:13.477
*** CLIENT ID:() 2014-09-16 18:10:13.477
*** SERVICE NAME:(SYS$USERS) 2014-09-16 18:10:13.477
*** MODULE NAME:(SQL*Plus) 2014-09-16 18:10:13.477
*** ACTION NAME:() 2014-09-16 18:10:13.477

oer 8102.2 - obj# 52, rdba: 0x00406e78(afn 1, blk# 28280)
kdk key 8102.2:
  ncol: 1, len: 4
  key: (4):  03 c2 26 45   ++++ 读取到的键值是03 c2 26 45  (通过vi搜索 8102.2)
  mask: (4096):
 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

通过上诉的 分析 ,现在我们基本可以确定,问题是这样的:
在文件1 块28280中有一个索引条目,它应该指向CON$表中 CON#=3768 这一条记录,
这个索引条目 的索引键 应该是 3768 (对应16进制为c2 26 45) ,它的ROWID应该就是CON$表上 CON#=3768 这一条记录的实际ROWID;
但是现在 这个索引条目的索引键不是3768,所以才导致了我们的问题。

SQL> select utl_raw.cast_to_number(‘c22645‘) from dual;

UTL_RAW.CAST_TO_NUMBER(‘C22645‘)
--------------------------------
                            3768


4、定位问题

知道了问题所在,那现在就是定位具体错误位置的时候了,根据上面的分析,
我们首先要得到CON$表中 CON#=3764 这一行的实际ROWID:
SQL> select dbms_rowid.rowid_relative_fno(rowid) file#,dbms_rowid.rowid_block_number(rowid) block#,
  2   dbms_rowid.rowid_row_number(rowid) row#
  3   from con$
  4   where name=‘_NEXT_CONSTRAINT‘  --AND con#=3768;

FILE#     BLOCK#       ROW#
---------- ---------- ----------
         1        289         12

ROWID的格式为还要不在解释?===》对象号,1号文件,289号块,12行

我把后面con#=‘3768‘注释掉了,这是因为用CON#=3768直接查不出来,原因应该就是这个查询使用了I_CON2引,而索引中没有个这个键值的条目

OK那么接下来我们来这个trace中搜索执行计划,你会发现如下信息:

============
Plan Table
============
--------------------------------------+-----------------------------------+
| Id  | Operation           | Name    | Rows  | Bytes | Cost  | Time      |
--------------------------------------+-----------------------------------+
| 0   | UPDATE STATEMENT    |         |       |       |     2 |           |
| 1   |  UPDATE             | CON$    |       |       |       |           |
| 2   |   INDEX UNIQUE SCAN | I_CON1  |     1 |    22 |     1 |  00:00:01 |
--------------------------------------+-----------------------------------+

Content of other_xml column
===========================
  db_version     : 11.2.0.3
  parse_schema   : SYS
  plan_hash      : 2574219287
  plan_hash_2    : 950544504
  Outline Data:
  /*+
    BEGIN_OUTLINE_DATA
      IGNORE_OPTIM_EMBEDDED_HINTS
      OPTIMIZER_FEATURES_ENABLE(‘11.2.0.3‘)
      DB_VERSION(‘11.2.0.3‘)
      OUTLINE_LEAF(@"UPD$1")
      INDEX(@"UPD$1" "CON$"@"UPD$1" ("CON$"."OWNER#" "CON$"."NAME"))
    END_OUTLINE_DATA
  */

5、我们来看一下52号对象到底是啥?

QL> SQL> col object_name for a30
SQL> set long 9999
SQL> select object_name,object_id,object_type from dba_objects where object_id=52;

OBJECT_NAME                     OBJECT_ID OBJECT_TYPE
------------------------------ ---------- -------------------
I_CON2                                 52 INDEX

分析下:select * from bootstrap$ where obj#52;

SQL> select dbms_metadata.get_ddl(‘INDEX‘,‘I_CON2‘,‘SYS‘) from dual;

DBMS_METADATA.GET_DDL(‘INDEX‘,‘I_CON2‘,‘SYS‘)
--------------------------------------------------------------------------------

CREATE UNIQUE INDEX "SYS"."I_CON2" ON "SYS"."CON$" ("CON#")
  PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
  TABLESPACE "SYSTEM"


6、现在我们得到了这个记录的实际ROWID,下一步就是去索引块里去查找了ROWID了。

dump 报错的索引块--rdba: 0x00406e78(afn 1, blk# 28280)

SQL> alter system dump datafile 1 block 28280;

System altered.

大家看一下最后一行数据的ROWID

more /u01/app/oracle/diag/rdbms/jfdb/jfdb/trace/jfdb_ora_5641.trc

row#266[4806] flag: ------, lock: 0, len=12, data:(6):  00 40 32 e6 00 67
col 0; len 3; (3):  c2 25 59
row#267[4794] flag: ------, lock: 0, len=12, data:(6):  00 40 32 e6 00 68
col 0; len 3; (3):  c2 25 5a
row#268[4782] flag: ------, lock: 0, len=12, data:(6):  00 40 32 e6 00 6a
col 0; len 3; (3):  c2 25 61
row#269[3954] flag: ------, lock: 0, len=12, data:(6):  00 40 01 21 00 0c
col 0; len 3; (3):  c2 26 46
----- end of leaf block dump -----

注意索引中的ROWID=文件号+块号+行号
文件号=0x004 ==>0000 0000 0100 ==》取前面10位的二进制:第1号文件
块号  =0x0121==>第289号
行号  =0x0c  ==>第12行

SQL> select dbms_rowid.rowid_relative_fno(rowid) file#,dbms_rowid.rowid_block_number(rowid) block#,
  2   dbms_rowid.rowid_row_number(rowid) row#
  3   from con$
  4   where name=‘_NEXT_CONSTRAINT‘  --AND con#=3768;

FILE#     BLOCK#       ROW#
---------- ---------- ----------
         1        289         12
创建主键约束时读取到的最大键值是c2 26 45,而index 键值中记录的next 值应该是c2 26 46.

说明索引键值与表上存的值不一致


7、那么怎么办呢 ?如何处理这个问题 ?我们直接对索引进行rebuild ,看行不行 ?

SQL> alter index I_CON2 rebuild;
alter index I_CON2 rebuild
*
ERROR at line 1:
ORA-00701: object necessary for warmstarting database cannot be altered

能不能rebuild ?

BBED> set block 28280
        BLOCK#          28280

BBED> map /v
 File: /u01/app/oracle/oradata/jfdb/system01.dbf (1)
 Block: 28280                                 Dba:0x00406e78
------------------------------------------------------------
 KTB Data Block (Index Leaf)

............................................
 sb2 kd_off[270]                            @148

ub1 freespace[3366]                        @688

ub1 rowdata[4066]                          @4054

ub4 tailchk                                @8188

row#271[3858] flag: ------, lock: 0, len=12, data:(6):  00 40 01 21 00 0c
col 0; len 3; (3):  c2 26 46
----- end of leaf block dump -----

前面我们讲过,对于index 键值的实际位置,其offset计算公式如下:
Itl           Xid                  Uba         Flag  Lck        Scn/Fsc
0x01   0x0002.01f.000000b5  0x00c04884.001f.01  CB--    0  scn 0x0000.00031295
0x02   0x000c.010.0000004c  0x0280000b.0021.35  C---    0  scn 0x0000.0020726a
0x03   0x000e.009.00000086  0x0280003a.005d.26  C---    0  scn 0x0000.0020766d

offset = kd_off + 44+8+itl*3 ,那么实际位置应该是:

3858+ 44+8+3*24=4076

SSQL> select  3858+ 44+8+3*24 from dual;

3858+44+8+3*24
--------------
          3982

8、利用 BBED 数据块和索引块(使索引键和表中的值一致)

BBED> d /v offset 3982 count 32
 File: /u01/app/oracle/oradata/jfdb/system01.dbf (1)
 Block: 28280   Offsets: 3982 to 4013  Dba:0x00406e78
-------------------------------------------------------
 03c22646 00000040 32e60069 03c22644 l .?&[email protected]?.i.?&D
 01000040 0121000c 03c22645 01000040 l [email protected]!...?&[email protected]

修改
SQL> select dbms_rowid.rowid_relative_fno(rowid) file#,dbms_rowid.rowid_block_number(rowid) block#,
  2   dbms_rowid.rowid_row_number(rowid) row#
  3   from con$
  4   where name=‘_NEXT_CONSTRAINT‘;

FILE#     BLOCK#       ROW#
---------- ---------- ----------
         1        289         12

BBED> set file 1 block 289
        FILE#           1
        BLOCK#          289

BBED> p *kdbr[12]
rowdata[0]
----------
ub1 rowdata[0]                              @1220     0x2c

BBED> x /rccnn
rowdata[0]                                  @1220    
----------
[email protected]: 0x2c (KDRHFL, KDRHFF, KDRHFH)
[email protected]: 0x00
[email protected]:    4

col    0[1] @1223: .
col   1[16] @1225: _NEXT_CONSTRAINT
col    2[3] @1242: 3768
col    3[1] @1246: 0
BBED> d /v offset 1242
 File: /u01/app/oracle/oradata/jfdb/system01.dbf (1)
 Block: 289     Offsets: 1242 to 1273  Dba:0x00400121
-------------------------------------------------------
 03c22645 01802c00 04018010 5f4e4558 l .?&E..,....._NEX
 545f434f 4e535452 41494e54 02c22601 l T_CONSTRAINT.?&.

BBED> modify /x 47 offset 1245
Warning: contents of previous BIFILE will be lost. Proceed? (Y/N) y
 File: /u01/app/oracle/oradata/jfdb/system01.dbf (1)
 Block: 289              Offsets: 1245 to 1276           Dba:0x00400121
------------------------------------------------------------------------
 4201802c 00040180 105f4e45 58545f43 4f4e5354 5241494e 5402c226 01802c00

<32 bytes per line>

BBED> sum apply
Check value for File 1, Block 289:
current = 0x1ae6, required = 0x1ae6

修改索引块
BBED> set file 1 block 28280
        BLOCK#          28280

BBED> d /v offset 3982 count 32
 File: /u01/app/oracle/oradata/jfdb/system01.dbf (1)
 Block: 28280   Offsets: 3982 to 4013  Dba:0x00406e78
-------------------------------------------------------
 03c22646 00000040 32e60069 03c22644 l .?&[email protected]?.i.?&D
 01000040 0121000c 03c22645 01000040 l [email protected]!...?&[email protected]

BBED> modify /x 47 offset 3985
 File: /u01/app/oracle/oradata/jfdb/system01.dbf (1)
 Block: 28280            Offsets: 3985 to 4016           Dba:0x00406e78
------------------------------------------------------------------------
 47000000 4032e600 6903c226 44010000 40012100 0c03c226 45010000 4032e600

<32 bytes per line>

BBED> sum apply;
Check value for File 1, Block 28280:
current = 0x352f, required = 0x352f

这个操作完毕后,可以重启数据库,然后测一下建主键。

SQL> conn gyj/gyj
Connected.
SQL> shutdown immediate;
ORA-01031: insufficient privileges
SQL> conn / as sysdba
Connected.
SQL> shutdown immediate;
Database closed.
Database dismounted.
ORACLE instance shut down.
SQL> startup
ORACLE instance started.

Total System Global Area 1570009088 bytes
Fixed Size                  2228704 bytes
Variable Size            1442844192 bytes
Database Buffers          117440512 bytes
Redo Buffers                7495680 bytes
Database mounted.
Database opened.
SQL> conn gyj/gyj
Connected.
SQL> alter table gyj_1000 add primary key(id);

Table altered.

时间: 2024-11-20 20:40:10

利用bbed来修复ora-08102错误的相关文章

利用BBED恢复UPDATE修改前的值

实验过程如下: 1.创建表guo_test1 [email protected]> create table guoyJoe_t1(id int,name varchar2(10)); Table created. [email protected]> insert into guoyJoe_t1 values(1,'guoyJoe'); 1 row created. [email protected]> insert into guoyJoe_t1 values(1,'tom'); 1

利用BBED恢复数据文件头

转载请注明出处:http://blog.csdn.net/guoyjoe/article/details/31018075 @@@@@@@利用BBED模拟损坏5文件1号块(文件头) BBED> copy file 4 block 4 to file 5 block 1 File: /u01/app/oracle/oradata/PROD/tp01.dbf (5) Block: 1 Offsets: 0 to 19 Dba:0x01400001 --------------------------

关于oracle 11g导出数据时 报 ORA 1455错误的处理

由于导出的该用户的表可能存在空数据表,那么可能就会出现此其异常. 首先: 查看: SQL>show parameter deferred_segment_creation; 如果为TRUE,则将该参数改为FALSE: 在sqlplus中,执行如下命令: SQL>alter system set deferred_segment_creation=false; 然后: 可以针对数据表.索引.物化视图等手工分配Extent SQL>Select 'alter table '||table_n

在linux环境下利用mmm命令编译android项目错误记录

此篇文章建立在之前的三篇文章的基础之上(本次内容主要参考老罗的<android源码情景分析一书>): 源码编译 内核编译 adb连接模拟器 ------------------------------------------------------------------------------------ 之后,在android源码环境中编写了一个简单的android程序HelloAndroid. 文件结构如下: ~/android/packages/experimental/HelloAn

利用linux信号机制调试段错误(Segment fault)

在实际开发过程中,大家可能会遇到段错误的问题,虽然是个老问题,但是其带来的隐患是极大的,只要出现一次,程序立即崩溃中止.如果程序运行在PC中,segment fault的调试相对比较方便,因为可以通过串口.显示器可以查看消息,只要程序运行,通过GDB调试工具即可捕捉产生segment fault的具体原因.但是不知大家有没有想法,当程序运行在嵌入式设备上时,你所面临资源的缺乏,你没有串口打印信息,没有显示器可查看,你不知道程序运行的状态,如果程序的产生segment falut这种bug发生的周

如何解决Greenplum中无法通过标准命令修复的元数据错误

Greenplum的可靠性还是没法和传统商业数据库相比,它跑着跑着就会把自己的元数据给跑乱,有些是可以通过命令修复的,有些则只能直接去增删改system catalog.本文结合一个具体错误,介绍如何操作system catalog解决元数据错误. 现象 使用gpcheckcat -p 5432 databasename检查数据库时,将报出类似如下的输出: Relation oid: 12345678 Relation name: None.None Name of test which fou

MySQL利用xtrabackup在线修复或新增从库

如果数据库的数据量很大,表大小有几十个G,利用mysqldump导出备份会消耗非常长的时间,会对数据库产生不稳定风险,这时可以利用xtrabackup工具在线复制主库文件,利用复制出来的主库文件可以修复从库故障或新增从库实例 主库IP:192.168.1.1从库IP:192.168.1.2 主库和从库服务器都需要安装以下环境安装必须的依赖环境yum install libssl.so.6 -yln -sf /usr/lib64/libssl.so.10 /usr/lib64/libssl.so.

修复数据库不一致性错误的方法

declare @dbname sysname要use master alter database UFDATA_002_2017 set single_user      ---------------这个不好使,可以用 <use master> + < EXEC sp_dboption 'UFDATA_002_2017', 'single user', 'TRUE'>dbcc checkdb ('UFDATA_002_2017',repair_rebuild)   ------

centos7利用系统镜像修复grub

1 故障描述 由于错误操作,导致grub配置文件失效,系统开机后一直卡在下面的画面. 2 解决办法 这时候,就要利用系统镜像光盘,进入修复模式,然后按下面图示操作 进入镜像的shell环境,如下图所示,继续操作. 恢复完成,exit退出镜像shell环境,然后reboot重启即可,系统就能正常登陆了. 原文地址:https://www.cnblogs.com/blog-tim/p/12331182.html