Oracle BBED修复数据库

来源:这里教程网 时间:2026-03-03 18:12:48 作者:

BBED  是Block Browser/Editor的缩写,是Oracle的一个内部工具,不对外发布文档及支持。正因为如此,所以其功能强大,可以直接修改block上的内容,因此很显然可以通过BBED来修改表上的数据,直接绕过通过SQL语句对表的操作。因此当数据库出现极端的启动故障时,可以考虑此工具作为最后的抢救手段。

 

的BBED在windows 平台下的$ORACLE_HOME/bin下可以找到(从9i开始没有了),而 在linux上面有,需要编译。

在9i/10g中连接生成bbed:

       $ cd $ORACLE_HOME/rdbms/lib

       $ make-f ins_rdbms.mk $ORACLE_HOME/rdbms/lib/bbed

 BBED  是Oracle 内部使用的命令,所以Oracle 不提供技术支持。 为了安全,BBED设置了口令保护,默认密码为blockedit。  还需要注意的是bbed直接修改文件有很大的风险,使用需要慎重。最好先做好备份,以防出现错误无法回退。

     

字节顺序是指占内存多于一个字节类型的数据在内存中的存放顺序,通常有小端(little-endian)、大端(big-endian)两种字节顺序。小端字节序指低字节数据存放在内存低地址处,高字节数据存放在内存高地址处;大端字节序是高字节数据存放在低地址处,低字节数据存放在高地址处。考虑    0x1234abcd  (0xcd  是低位,0x12是高位,这是人类的书写顺序),  写入到以  0x0000  开始的内存地址中,  那么它在内存中的存储可能有如下两种情况:

注意  ,  我们的书写字数据表示法是从高字节位  --->  低字节位(从左到右)

如,十进制数  “一百二十”我们手工书写出来则是  120  ,第一个数字  1  就是高字节位。

生长方向为  从左到右  由低到高  (  这是不变的  )

0x0001

0x0002

0x0003

0x0004

little-endian

0xcd

0xab

0x34

0x12

big-endian

0x12

0x34

0xab

0xcd

Oracle  内可以通过一张视图查询出各主机OS平台的大/小字节序,如下:

SQL>select * from v$transportable_platform

PLATFORM_ID PLATFORM_NAME ENDIAN_FORMAT

----------- --------------------------------------------- --------------

          1 Solaris[tm] OE (32-bit) Big

          2 Solaris[tm] OE (64-bit) Big

          7 Microsoft Windows IA (32-bit) Little

         10 Linux IA (32-bit) Little

          6 AIX-Based Systems (64-bit) Big

          3 HP-UX (64-bit) Big

          5 HP Tru64 UNIX Little

          4 HP-UX IA (64-bit) Big

         11 Linux IA (64-bit) Little

         15 HP Open VMS Little

          8 Microsoft Windows IA (64-bit) Little

          9 IBM zSeries Based Linux Big

         13 Linux x86 64-bit Little

         16 Apple Mac OS Big

         12 Microsoft Windows x86 64-bit Little

         17 Solaris Operating System (x86) Little

         18 IBM Power Based Linux Big

         20 Solaris Operating System (x86-64) Little

         19 HP IA Open VMS Little

可以看出来X86平台cpu都是little-endian,而小型机上使用的精简指令集架构cpu则多采用big-endian。了解这个对于适用bbed很重要,因为bbed里面就是用16进制显示的,修改也要采用16进制数。在不同平台下这个修改的16进制数据就需要根据数据库所在平台是little-endian或者big-endian来修改。

下面是几个常用的:

set   设定当前的环境

show   查看当前的环境参数,跟  sqlplus  的同名命令类似。

dump   列出指定  block  的内容

find   在指定的  block  中查找指定的字符串,结果是显示出字符串,及其偏移量  --offset  ,偏移量就是在  block  中的字节数

modify   修改指定  block  的指定偏移量的值,可以在线修改。

copy   把一个  block  的内容  copy  到另一个  block 

verify   检查当前环境是否有坏块

sum   计算  block    checksum    modify  之后  block  就被标识为坏块,  current checksum    reqired checksum  不一致,  sum  命令可以计算出新的  checksum  并应用到当前块。

undo   回滚当前的修改操作,如果手误做错了,  undo  一下就  ok  了,回到原来的状态。

revert   回滚所有之前的修改操作,意思就是   undo all

BBED> help all  可以查看更详细的帮助信息

 

某客户数据库因为机房突然掉电导致数据库宕机。而更倒霉的是rman备份文件也被损坏,只能恢复出数据文件,而归档日志则无法恢复。备份集恢复出来的数据因不一致导致数据库无法正常open。

查询各数据文件scn结果如下

SQL> select file#,checkpoint_change#,resetlogs_change#,fuzzy,status from v$datafile_header order by 2;

        10           26271884            994063 NO  ONLINE

        16           26271884            994063 YES ONLINE

         7           26271884            994063 NO  ONLINE

        13           26271884            994063 NO  ONLINE

         5           26271884            994063 NO  ONLINE

        17           26271884            994063 YES ONLINE

         8           26271895            994063 NO  ONLINE

         6           26271895            994063 NO  ONLINE

        18           26271895            994063 YES ONLINE

         2           26271895            994063 NO  ONLINE

        14           26271895            994063 YES ONLINE

        11           26271895            994063 NO  ONLINE

         4           26271915            994063 YES ONLINE

         1           26271915            994063 NO  ONLINE

        15           26271915            994063 YES ONLINE

        12           26271915            994063 NO  ONLINE

         3           26271915            994063 NO  ONLINE

         9           26271915            994063 NO  ONLINE

SQL> select max(checkpoint_change#) from v$datafile_header;

               26271915  最大的scn

SQL> select min(checkpoint_change#) from v$datafile_header;

               26271884  最小的scn

查询所有小于最大的scn的数据文件信息

SQL> select file#||' '||name||' '||bytes from v$datafile_header where checkpoint_change#<26271915;

2 E:\APP\ADMINISTRATOR\ORADATA\ORCL\SYSAUX01.DBF 880803840

5 E:\APP\ADMINISTRATOR\ORADATA\DATE\USERS05.DBF 32212254720

6 E:\APP\ADMINISTRATOR\ORADATA\DATE\USERS06.DBF 32212254720

7 E:\APP\ADMINISTRATOR\ORADATA\DATE\USERS07.DBF 32212254720

8 E:\APP\ADMINISTRATOR\ORADATA\DATE\USERS08.DBF 32212254720

10 E:\APP\ADMINISTRATOR\ORADATA\DATE\USERS10.DBF 32212254720

11 E:\APP\ADMINISTRATOR\ORADATA\DATE\USERS11.DBF 32212254720

13 E:\APP\ADMINISTRATOR\ORADATA\DATE\USERS13.DBF 32212254720

14 E:\APP\ADMINISTRATOR\ORADATA\DATE\USERS14.DBF 32212254720

16 E:\APP\ADMINISTRATOR\ORADATA\DATE\USERS16.DBF 32212254720

17 E:\APP\ADMINISTRATOR\ORADATA\DATE\USERS17.DBF 15644753920

18 E:\APP\ADMINISTRATOR\ORADATA\DATE\USERS18.DBF 15571353600

这12个数据文件就是我们要通过bbed修改的文件,首先在操作系统级别把这几个文件全部备份一遍。

因为1号文件的scn值就是最大scn值,故可以直接以该文件作为参考修改另外的12个文件

SQL> select file#||' '||name||' '||bytes from v$datafile_header where file#=1;

1 E:\APP\ADMINISTRATOR\ORADATA\ORCL\SYSTEM01.DBF 933232640

 

1.  创建文件列表参数文件,将以上  sql  查询结果保存到一个文本文档中如  e:\filelist.txt

2.  创建参数文件,该参数文件指定了  bbed  的基本环境    e:\bbedpar.txt

blocksize=8192

listfile=e:\filelist.txt

mode=edit 

 

  3  )使用参数文件连接  bbed

 

[oracle@dg1 ~]$ bbed parfile=  e:\bbedpar.tx

Password:   blockedit

BBED: Release 2.0.0.0.0 - Limited Production on Tue Jun 11 15:21:27 2015

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

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

 

BBED> set dba 1  ,1 设定位置为1号文件的第一个数据块,数据文件头就在这里

BBED> p kcvfh

BBED-00400: invalid blocktype (00)

正常情况下第一个数据块就是文件头,但是这里报错应该是跟我使用的是在oracle 10g版本下编译出来的bbed有关,用11g版本编译出来的bbed则不会有这个问题。通过这里发现用10g版本的bbed修改11g数据文件,则数据文件头是2号块。

BBED> set dba 1,2

BBED> p kcvfh

struct kcvfh, 340 bytes                     @0

   struct kcvfhbfh, 20 bytes                @0

      ub1 type_kcbh                         @0        0x0b

      ub1 frmt_kcbh                         @1        0xa2

      ub1 spare1_kcbh                       @2        0x00

      ub1 spare2_kcbh                       @3        0x00

      ub4 rdba_kcbh                         @4        0x00800001

      ub4 bas_kcbh                          @8        0x00000000

      ub2 wrp_kcbh                          @12       0x0000

      ub1 seq_kcbh                          @14       0x01

      ub1 flg_kcbh                          @15       0x04 (KCBHFCKV)

      ub2 chkval_kcbh                       @16       0x74bd

      ub2 spare3_kcbh                       @18       0x0000

   struct kcvfhhdr, 76 bytes                @20

 

显示1号文件2号数据块offset为484开始的内容,v$data_file_header的checkpoint_change# 列值就取自这里

BBED> dump offset 484 dba 1,2

File: E:\APP\ADMINISTRATOR\ORADATA\ORCL\SYSTEM01.DBF (1)

 Block: 2                Offsets:  484 to  995           Dba:0x00400002

------------------------------------------------------------------------

   abe09001  00000000 55de9134 01000000 11090000 551b0000 1000f54d 02000000

……

对比显示2号文件2号数据块offset为484开始的内容

BBED> dump offset 484 dba 2,2

 File: E:\APP\ADMINISTRATOR\ORADATA\ORCL\SYSAUX01.DBF (2)

 Block: 2                Offsets:  484 to  995           Dba:0x00800002

------------------------------------------------------------------------

   97e09001  00000000 51de9134 01000000 11090000 c01a0000 1000db21 02000000

……

而根据v$datafile_header.checkpoint_change# 转换应该是

由于X86_64架构下的windows属于     Little endian  ,  故通过bbed看到的16进制值是反向的,把上面查询到的v$datafile_header.checkpoint_change#转换成16进制值则可以发现正好根dump出来的内容一致。

SQL> select to_char(26271895,'xxxxxxxx') from dual;

TO_CHAR(26271895,'XXXXXXXX')

----------------------------

  190e097   其在内存里面根据     Little endian  存储为 97e09001

SQL> select to_char(26271915,'xxxxxxxx') from dual;

 

TO_CHAR(26271915,'XXXXXXXX')

----------------------------

  190e0ab  其在内存里面根据     Little endian  存储为 abe09001

 

将2号文件的checkpoint_change# 修改成同一号文件一致

  BBED> modify /x  abe09001  offset 484

 File: E:\APP\ADMINISTRATOR\ORADATA\ORCL\SYSAUX01.DBF (2)

 Block: 2                Offsets:  484 to  995           Dba:0x00800002

------------------------------------------------------------------------

 abe09001 00000000 51de9134 01000000 11090000 c01a0000 1000db21 02000000

 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000

 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000

 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000

 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000

 0c000c00 0c000100 00000000 00000000 00000000 02008000 d07e4101 00000000

 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000

 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000

 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000

 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000

 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000

 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000

 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000

 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000

 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000

 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000

 <32 bytes per line>

BBED> verify

DBVERIFY - Verification starting

FILE = E:\APP\ADMINISTRATOR\ORADATA\ORCL\SYSAUX01.DBF

BLOCK = 1

 

Block 1 is corrupt

***

Corrupt block relative dba: 0x00800001 (file 0, block 1)

Bad header found during verification

Data in bad block -

 type: 11 format: 162 rdba: 0x00800001

 last change scn: 0x0000.00000000 seq: 0x1 flg: 0x04

 consistency value in tail: 0x00000b01

 check value in block header: 0x74bd, computed block checksum: 0x3c

 spare1: 0x0, spare2: 0x0, spare3: 0x0

***

DBVERIFY - Verification complete

 

Total Blocks Examined         : 1

Total Blocks Processed (Data) : 0

Total Blocks Failing   (Data) : 0

Total Blocks Processed (Index): 0

Total Blocks Failing   (Index): 0

Total Blocks Empty            : 0

Total Blocks Marked Corrupt   : 1  这里就是刚刚修改过的块,其自动被标记为损坏

Total Blocks Influx           : 0

 

BBED> sum apply   计算修改后的数据块的checksum值,然后写入数据块的offset

Check value for File 2, Block 2:

current = 0x7481, required = 0x7481

再次查询,可以看到2号文件的checkpoint_change# 已经更正过来

SQL> select file#,checkpoint_change#,resetlogs_change#,fuzzy from v$datafile_header where file# in(1,2);

     FILE# CHECKPOINT_CHANGE# RESETLOGS_CHANGE# FUZ

---------- ------------------ ----------------- ---

         1           26271915            994063 NO

         2           26271915            994063 NO

按照此步骤修改余下的11  个文件,过程略,修改完成后

SQL> alter database open resetlogs;

alter database open resetlogs

*

 1  行出现错误:

ORA-01194:  文件 4  需要更多的恢复来保持一致性

ORA-01110:  数据文件 4: 'E:\APP\ADMINISTRATOR\ORADATA\ORCL\USERS01.DBF'

 

此时检查发现数据文件checkpoint_change#  已经一致,但是个别文件fuzzy  yes  ,这个说明数据文件里面的某些块的scn  比数据文件头的checkpoint_change#  还大,也需要通过日志恢复,而目前环境也不可能实现,继续bbed  修改。

修改fuzzy  ,该标记为在数据文件头的offset=138  处,表示no  ,也就是修改成即可。

BBED> d offset 138 dba 1,2

 File: E:\APP\ADMINISTRATOR\ORADATA\ORCL\SYSTEM01.DBF (1)

 Block: 2                Offsets:  138 to  649           Dba:0x00400002

------------------------------------------------------------------------

   0020ca0a 00005e1b 9434c90a 00000000 00000000 00000000 00000000 00000000

 

 BBED> d offset 138 dba 4,2

 File: E:\APP\ADMINISTRATOR\ORADATA\ORCL\USERS01.DBF (4)

 Block: 2                Offsets:  138 to  649           Dba:0x01000002

------------------------------------------------------------------------

   4000c70a 00005e1b 9434c60a 00000000 00000000 00000000 00000000 00000000

 BBED> set dba 4,2

BBED> m /x 00 offset 138

BBED> sum apply

重复此步骤直到所有文件修改完毕。最后 alter database open resetlogs  成功打开数据库。打开后发现一张核心表最近一天的导出报错,该表基本上每时每刻都在插入数据,虽然bbed  修改后强制打开了数据库,但是数据的一致性实际上不可避免的要被破坏,但是至少恢复了上一次备份到断电前一天的数据。

 

Bbed  作为oracle的内部工具,确实具备很多强大的功能,但是也并非无所不能,极端情况下可以利用它来修改数据文件继而打开数据库,单是内部的数据一致性是不能得到保障的,因此一定要提前备份数据。

相关推荐