前言:
Oracle数据库的bootstrap$表对于数据库非常重要,它在数据库的启动过程中引导数据库字典的初始化,在有些极端宕机或者恶意破坏下,可能出现bootstrap$的损坏,本文主要讲述如何进行bootstrap$的恢复。
什么是bootstrap$表
bootstrap$是Oracle的一个数据字典基表,里面存放着创建数据字典的DDL语句,作用类似于操作系统的引导盘,在数据库进行open的过程中,会去system表空间文件1固定的位置读取bootstrap$表初始化一系列的数据字典。
SQL> desc bootstrap$;
Name Null? Type
----------------------------------------- -------- ----------------------------
LINE# NOT NULL NUMBER
OBJ# NOT NULL NUMBER
SQL_TEXT NOT NULL VARCHAR2(4000)
SQL> select obj#,sql_text from bootstrap$ where rownum<5
OBJ# SQL_TEXT
---------- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-1 8.0.0.0.0
0 CREATE ROLLBACK SEGMENT SYSTEM STORAGE ( INITIAL 112K NEXT 56K MINEXTENTS 1 MAXEXTENTS 32765 OBJNO 0 EXTENTS (FILE 1 BLOCK 128))
20 CREATE TABLE ICOL$("OBJ#" NUMBER NOT NULL,"BO#" NUMBER NOT NULL,"COL#" NUMBER NOT NULL,"POS#" NUMBER NOT NULL,"SEGCOL#" NUMBER NOT NULL,"SEGCOLLENGTH" NUMBER NOT NULL,"OFFSET" NUMBER NOT NULL,"INTCOL#" NUMBER NOT NULL,"SPARE1" NUMBER,"SPARE2" NUMBER,"SPARE3" NUMBER,"SPARE4" VARCHAR2(1000),"SPARE5" V
ARCHAR2(1000),"SPARE6" DATE) STORAGE ( OBJNO 20 TABNO 4) CLUSTER C_OBJ#(BO#)
42 CREATE INDEX I_ICOL1 ON ICOL$(OBJ#) PCTFREE 10 INITRANS 2 MAXTRANS 255 STORAGE ( INITIAL 64K NEXT 1024K MINEXTENTS 1 MAXEXTENTS 2147483645 PCTINCREASE 0 OBJNO 42 EXTENTS (FILE 1 BLOCK 384))
bootstrap$表的位置
Oracle11g:file_id:1 block:520-527
SQL> select * from v$version;
BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
PL/SQL Release 11.2.0.4.0 - Production
CORE 11.2.0.4.0 Production
TNS for Linux: Version 11.2.0.4.0 - Production
NLSRTL Version 11.2.0.4.0 - Production
---在system表空间1号文件,1个extent,从520开始,共8个块
SQL> select *
from dba_extents
where segment_name='BOOTSTRAP$'
OWNER SEGMENT_NAME PARTITION_NAME SEGMENT_TYPE TABLESPACE_NAME EXTENT_ID FILE_ID BLOCK_ID BYTES BLOCKS RELATIVE_FNO
---------- -------------------- -------------------- ------------------ ------------------------------ ---------- ---------- ---------- ---------- ---------- ------------
SYS BOOTSTRAP$ TABLE SYSTEM 0 1 520 65536 8 1
---数据分布在file 1块521,522,523
SQL> select distinct dbms_rowid.rowid_relative_fno(rowid),dbms_rowid.rowid_block_number(rowid)
from bootstrap$
order by 2;
DBMS_ROWID.ROWID_RELATIVE_FNO(ROWID) DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)
------------------------------------ ------------------------------------
1 521
1 522
1 523
Oracle19c:file_id:1 block:520-527
SYS> select banner from v$version;
BANNER
--------------------------------------------------------------------------------
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
----在system表空间1号文件,1个extent,从520开始,共8个块
select *
from dba_extents
where segment_name='BOOTSTRAP$';SYS@orcl> SYS@orcl> SYS@orcl> SYS@orcl> SYS@orcl> SYS@orcl> 2 3
OWNER SEGMENT_NAME PARTITION_NAME SEGMENT_TYPE TABLESPACE_NAME EXTENT_ID FILE_ID BLOCK_ID BYTES BLOCKS RELATIVE_FNO
---------- -------------------- -------------------- ------------------ ------------------------------ ---------- ---------- ---------- ---------- ---------- ------------
SYS BOOTSTRAP$ TABLE SYSTEM 0 1 520 65536 8 1
---数据分布在file 1块521,522,523
SQL> select distinct dbms_rowid.rowid_relative_fno(rowid),dbms_rowid.rowid_block_number(rowid)
from bootstrap$
order by 2;
DBMS_ROWID.ROWID_RELATIVE_FNO(ROWID) DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)
------------------------------------ ------------------------------------
1 521
1 522
1 523
恢复bootstrap$表测试
在进行测试之前,先备份一下bootstrap$
---对于放在rman里面的datafile文件,先通过rman backup as copy或者cp备份到本地
backup as copy datafile 1 format '/backup/system01_%d_%s_%T.dbf';
---再通过dd进行备份
dd if=/backup/system01_DBOCS_16_20220709.dbf of=/backup/bootstrap.dbf bs=8192 skip=520 count=8
---通过strings可以看到,都是数据字典的DDL语句
[root@rac1 backup]# strings bootstrap.dbf |more
CREATE INDEX I_TS# ON CLUSTER C_TS# PCTFREE 10 INITRANS 2 MAXTRANS 255 STORAGE ( INITIAL 64K NEXT 1024K MINEXTENTS 1 MAXEXTENTS 2147483645 PCTINCREASE 0 OBJNO 7 EXTENTS (FILE 1 BLOCK 184)),
CREATE CLUSTER C_TS#("TS#" NUMBER) PCTFREE 10 PCTUSED 40 INITRANS 2 MAXTRANS 255 STORAGE ( INITIAL 64K NEXT 1024K MINEXTENTS 1 MAXEXTENTS 2147483645 PCTINCREASE 0 OBJNO 6 EXTENTS (FILE 1 BLOCK 176)),
通过dd模拟bootstrap$损坏
---对于存放在ASM的,需要先将数据文件拷贝到本地进行模拟损坏,再还原
dd if=/dev/zero of=/backup/system.dbf bs=8192 seek=520 count=8 conv=notrunc
启动数据库,在执行open时报错,显示bootstrap process failure
SQL> alter database open;
alter database open
*
ERROR at line 1:
ORA-01092: ORACLE instance terminated. Disconnection forced
ORA-00704: bootstrap process failure
ORA-01578: ORACLE data block corrupted (file # 1, block # 520)
ORA-01110: data file 1: '+DATA/dbocs/datafile/system01'
Process ID: 83985
Session ID: 191 Serial number: 3
有时,也会bootstrap$也遇到这种报错ora-00702
通过10046 跟踪open的过程
startup mount
oradebug setmypid
oradebug event 10046 trace name context forever,level 12
alter database open;
oradebug tracefile_name
oradebug event 10046 trace name context off
通过10046的trc日志可以发现,读取system01 的block 520失败
Byte offset to file# 1 block# 520 is 4259840
Incident 30265 created, dump file: /u01/app/oracle/diag/rdbms/dbocs/dbocs1/incident/incdir_30265/dbocs1_ora_88461_i30265.trc
ORA-01578: ORACLE data block corrupted (file # 1, block # 520)
ORA-01110: data file 1: '+DATA/dbocs/datafile/system01'
ORA-00704: bootstrap process failure
ORA-01578: ORACLE data block corrupted (file # 1, block # 520)
ORA-01110: data file 1: '+DATA/dbocs/datafile/system01'
ORA-00704: bootstrap process failure
ORA-01578: ORACLE data block corrupted (file # 1, block # 520)
ORA-01110: data file 1: '+DATA/dbocs/datafile/system01'
通过之前备份的文件进行恢复,通常有三种方式dd,bbed以及rman备份恢复
方式一:dd
---对于存放在ASM的,需要先将数据文件拷贝到本地进行dd修复,在
ASMCMD> cp SYSTEM01 /backup/
---使用之前的备份进行覆盖
dd if=/backup/bootstrap.dbf of=/backup/SYSTEM01 bs=8192 seek=520 count=8 conv=notrunc
---也可以使用其他库的SYSTEM FILE 1文件或者备份类型copy的进行dd还原,因为位置是一样
dd if=/backup/system01_DBOCS_21_20220709.dbf of=/backup/SYSTEM01 bs=8192 count=8 seek=520 skip=520 conv=notrunc
---再还原到asm
ASMCMD> cp /backup/SYSTEM01 +data/dbocs/datafile/
---recover重新open
recover database;
alter database open;
方法二:bbed
使用之前,需要先编译一下bbed,在Oracle11g之后,安装软件默认是没有bbed工具
---将依赖文件拷贝到lib,mesg目录下
cp ssbbded.o $ORACLE_HOME/rdbms/lib
cp sbbdpt.o $ORACLE_HOME/rdbms/lib
cp bbedus.msb $ORACLE_HOME/rdbms/mesg
cp bbedus.msg $ORACLE_HOME/rdbms/mesg
---编译
make -f $ORACLE_HOME/rdbms/lib/ins_rdbms.mk BBED=$ORACLE_HOME/bin/bbed $ORACLE_HOME/bin/bbed
---使用BBED
BBED是Oracle 内部使用的命令,所以Oracle 不提供技术支持。为了安全,BBED设置了口令保护,默认密码为blockedit。
[oracle@db2 bin]$ bbed
Password:blockedit
使用bbed进行修复
---对于ASM文件,需要先拷贝到本地进行修复
---把进行修复的备份以及文件也加入listfile.par
[oracle@rac1 backup]$ cat listfile.par
1 /backup/SYSTEM01 2317352960
2 /backup/system01_DBOCS_21_20220709.dbf 2317352960
---进入bbed工具
[oracle@rac1 backup]$ bbed password=blockedit mode=edit blocksize=8192 listfile=/backup/listfile.par
BBED: Release 2.0.0.0.0 - Limited Production on Sat Jul 9 21:29:58 2022
Copyright (c) 1982, 2011, Oracle and/or its affiliates. All rights reserved.
************* !!! For Oracle Internal Use only !!! ***************
---info 确认文件可以识别
BBED> info
File# Name Size(blks)
----- ---- ----------
1 /backup/SYSTEM01 282880
2 /backup/system01_DBOCS_21_20220709.dbf 282880
BBED>
---set count 设置页面打印大小
BBED> set count 128
COUNT 128
---使用备份文件或者其他环境的文件,将对应位置的块拷贝到恢复文件
BBED>
copy file 2 block 520 to file 1 block 520
copy file 2 block 521 to file 1 block 521
copy file 2 block 522 to file 1 block 522
copy file 2 block 523 to file 1 block 523
copy file 2 block 524 to file 1 block 524
copy file 2 block 525 to file 1 block 525
copy file 2 block 526 to file 1 block 526
copy file 2 block 527 to file 1 block 527
---检查更新文件块头checksum
BBED> sum apply
Check value for File 1, Block 527:
current = 0xa54f, required = 0xa54f
BBED>
对于ASM文件,将修复好的文件还原到asm
---recover重新open
recover database;
alter database open;
方法三:rman备份恢复
如果备份完整,可以通过重新恢复数据文件datafile 1的方式
---重新恢复数据文件
rman target /
restore datafile 1
recover datafile 1
---再open数据库
alter database open
可以尝试通过rman进行坏块修复
---对数据库进行坏块扫描
RMAN> run {
allocate channel d1 type disk;
allocate channel d2 type disk;
allocate channel d3 type disk;
allocate channel d4 type disk;
backup validate check logical database;
release channel d1;
release channel d2;
release channel d3;
release channel d3;
}
---查看扫描坏块结果
set linesize 300
set pagesize 4000
select * from V$DATABASE_BLOCK_CORRUPTION ;
对于物理损坏的数据块,我们可以通过RMAN块介质恢复(BLOCK MEDIA RECOVERY)功能来完成受损块的恢复,而不需要恢复整个数据库或所有文件来修复这些少量受损的数据块。
但前提条件是你得有一个可用的RMAN备份存在
---使用rman进行块恢复:
RMAN> blockrecover datafile 1 block 520,521,522,523,524,525,526,527;
---块恢复后,执行BLOCKRECOVER CORRUPTION LIST,会自动按照V$DATABASE_BLOCK_CORRUPTION进行修复(耗时较长):
RMAN> BLOCKRECOVER CORRUPTION LIST;
---这个时候再访问v$database_block_corruption就看不到详细的坏块信息了:
SQL> select * from v$database_block_corruption;