天天看點

Oracle bootstrap$ 詳解

一. 官網說明

 Oracle官方文檔對Bootstrap$的說明:

​​UnderstandingBootstrap Of Oracle Database​​

​​http://www.cndba.cn/Dave/article/1356​​

In Oracle,Bootstrap refers to loading of metadata (data dictionary) before we OPEN thedatabase.

Bootstrap objects are classified as the objects (tables / indexes / clusters) with the object_id below 56 as bootstrap objects.

Object_id 在56以下的都作為bootstrap objects,這些對象都是Oracle 的核心對象,這裡為什麼是56,和Oracle 版本有關系,如果核心對象多,這裡的數字就會更大。

在之前的一篇Blog中有說明,10g中X$KCVFH中字段FHRDB對應的就是bootstrap$. 而FHRDB 對應的object id 就是56. 在Oracle11g中,這個bootstrap$對應的就是59.

​​Oracle 10g 中 X$KCVFH 說明​​

​​http://www.cndba.cn/dave/article/1348​​

These objects are mandatory to bring up an instance, as this contains the most important metadata of the database.

1.1 What happens on database startup?

This shall beexplained by setting theSQL_TRACE while opening the database.

用sysdba 執行如下步驟可以檢視在資料庫OPEN時都有哪些操作:

(1)STARTUP MOUNT;

(2)ALTER SESSION SET EVENTS ’10046TRACE NAME CONTEXT FOREVER, LEVEL 12′;

(3)ALTER DATABASE OPEN;

(4)ALTER SESSION SET EVENTS ’10046TRACE NAME CONTEXT OFF’;

(5)SHOW PARAMETER USER_DUMP_DEST

(6)ORADEBUG SETMYPID

(7)ORADEBUG TRACEFILE_NAME

示例:

[oracle@dave ~]$ sqlplus / as sysdba;

SQL*Plus: Release 11.2.0.3.0 Production onMon Oct 31 10:13:01 2011

Copyright (c) 1982, 2011, Oracle.  All rights reserved.

Connected to an idle instance.

SQL> startup mount;

ORACLE instance started.

Total System Global Area 1043886080 bytes

Fixed Size                  2234960 bytes

Variable Size             838862256 bytes

Database Buffers          197132288 bytes

Redo Buffers                5656576 bytes

Database mounted.

SQL> alter session set events '10046 trace name context forever,level 12';

Session altered.

SQL> alter database open;

Database altered.

SQL> alter session set events '10046trace name context off';

Session altered.

SQL> oradebug setmypid

Statement processed.

SQL> oradebug tracefile_name

/u01/app/oracle/diag/rdbms/anqing/anqing/trace/anqing_ora_4864.trc

​​Oracle oradebug 指令 使用說明​​

檢視trace 檔案,這個trace 的内容很多,這裡截取部分内容:

*** 2011-10-31 10:15:26.314

WAIT #47868535613696: nam='db filesequential read' ela= 34204 file#=1 block#=520 blocks=1 obj#=-1tim=1320027326313943

=====================

PARSING IN CURSOR #47868535605544 len=188 dep=1uid=0 oct=1 lid=0 tim=1320027326467068 hv=4006182593 ad='9e067188'sqlid='32r4f1brck

zq1'

create table bootstrap$ (line#         number not null,   obj#           number not null,   sql_text  varchar2(4000) not null)   storage(initial 50K objno 59 extents (file 1 block 520))

END OF STMT

PARSE#47868535605544:c=28002,e=149060,p=0,cr=0,cu=0,mis=1,r=0,dep=1,og=4,plh=0,tim=1320027326467068

EXEC#47868535605544:c=0,e=18705,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,plh=0,tim=1320027326486816

CLOSE #47868535605544:c=0,e=0,dep=1,type=0,tim=1320027326487664

=====================

PARSING IN CURSOR #47868535605544 len=55dep=1 uid=0 oct=3 lid=0 tim=1320027326527387 hv=2111436465 ad='9e055980'sqlid='6apq2rjyxmx

pj'

select line#, sql_textfrom bootstrap$ where obj# != :1

END OF STMT

PARSE#47868535605544:c=28002,e=39628,p=0,cr=0,cu=0,mis=1,r=0,dep=1,og=4,plh=0,tim=1320027326527353

BINDS #47868535605544:

 Bind#0

 oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00

 oacflg=08 fl2=0001 frm=00 csi=00 siz=24 off=0

 kxsbbbfp=2b89430f84e0  bln=22  avl=02 flg=05

  value=59

EXEC#47868535605544:c=12000,e=101181,p=0,cr=0,cu=0,mis=1,r=0,dep=1,og=4,plh=867914364,tim=1320027326630459

……

STAT #47868535605544 id=1cnt=59 pid=0 pos=1 obj=59 op='TABLE ACCESS FULL BOOTSTRAP$ (cr=61 pr=4 pw=0time=49592 us)'

WAIT #47868535605544: nam='latch: sharedpool' ela= 2917 address=1611695672 number=307 tries=0 obj#=59tim=1320027326745870

CLOSE#47868535605544:c=0,e=84,dep=1,type=0,tim=1320027326747472

…..

CREATE ROLLBACK SEGMENT SYSTEM STORAGE (  INITIAL 112K NEXT 56K MINEXTENTS 1 MAXEXTENTS32765 OBJNO 0 EXTENTS (FILE 1 BLOCK 128))

……

CREATE CLUSTER C_OBJ#("OBJ#"NUMBER) PCTFREE 5 PCTUSED 40 INITRANS 2 MAXTRANS 255 STORAGE (  INITIAL 136K NEXT 200K

……

CREATE TABLE TAB$("OBJ#" NUMBERNOT NULL,"DATAOBJ#" NUMBER,"TS#" NUMBER NOTNULL,"FILE#" NUMBER NOT

……

CREATE TABLE FILE$("FILE#" NUMBERNOT NULL,"STATUS$" NUMBER NOT NULL,"BLOCKS" NUMBER NOTNULL,"TS#" NUMBER,"RELFILE#" NUMBER,"MAXEXT

……

通過以上的說明,可以看出可以在資料庫Open 階段會建立一些資料字典。

​​Oracle 資料字典 說明​​

​​Oracle 動态性能視圖​​

​​http://www.cndba.cn/Dave/article/1449​​

這裡重點看一下:

create table bootstrap$ (line# number not null, obj# number not null, sql_textvarchar2(4000) not null)storage (initial 50K objno 56 extents (file 1 block377))

This sys.bootstrap$ table contains the DDL’s for other bootstrap tables (object_idbelow 56).

Actually these tables were createdinternally by the time of database creation (by sql.bsq),The create DDL passedbetween MOUNT and OPEN stage will be executed throughdifferent driverroutines. In simple words these are not standard CREATE DDLs.

While starting up the database oracle will load these objects into memory(shared_pool),(ie) itwill assign the relevant object number and refer to the datafile and the blockassociated with that.

And suchoperations happen only while warm startup.

@ The internals of the above explained in‘kqlb.c’.

我們從bootstrap$中檢視一下object_id 小于56的對象内容:

Now a queryexecutedagainst the sys.bootstrap$ table, which holds the create sql’s forother basetables.

SQL>select line#, sql_text from bootstrap$ ;

Subsequently it will create those objectsby running those queries.

Object number 0 – (System Rollback Segment)

Object number 2 to 55 (Other base tables)

Object number 1 is NOT used by any of the objects.

以下是Oracle 11g的查詢結果:

SQL> select obj#, substr(sql_text,1,50)from bootstrap$ order by 1 desc;

     OBJ# SUBSTR(SQL_TEXT,1,50)

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

       59CREATE TABLE BOOTSTRAP$("LINE#" NUMBER NOT NULL,"O

--注意這裡的BOOTSTRAP$ 對象變成了59

       58 CREATE UNIQUE INDEX I_CCOL2 ON CCOL$(CON#,INTCOL#)

       57 CREATE INDEX I_CCOL1 ON CCOL$(CON#,COL#) PCTFREE 1

       56 CREATE INDEX I_CDEF4 ON CDEF$(ENABLED) PCTFREE 10

       55 CREATE INDEX I_CDEF3 ON CDEF$(ROBJ#) PCTFREE 10 IN

       54 CREATE INDEX I_CDEF2 ON CDEF$(OBJ#) PCTFREE 10 INI

       53 CREATE UNIQUE INDEX I_CDEF1 ON CDEF$(CON#) PCTFREE

       52 CREATE UNIQUE INDEX I_CON2 ON CON$(CON#) PCTFREE 1

       51 CREATE UNIQUE INDEX I_CON1 ON CON$(OWNER#,NAME) PC

       50 CREATE UNIQUE INDEX I_COL3 ON COL$(OBJ#,INTCOL#) P

       49 CREATE INDEX I_COL2 ON COL$(OBJ#,COL#) PCTFREE 10

       48 CREATE UNIQUE INDEX I_COL1 ON COL$(OBJ#,NAME) PCTF

       47 CREATE UNIQUE INDEX I_USER2 ON USER$(USER#,TYPE#,S

       46 CREATE UNIQUE INDEX I_USER1 ON USER$(NAME) PCTFREE

       45 CREATE UNIQUE INDEX I_TS1 ON TS$(NAME) PCTFREE 10

       44 CREATE UNIQUE INDEX I_FILE2 ON FILE$(TS#,RELFILE#)

       43 CREATE UNIQUE INDEX I_FILE1 ON FILE$(FILE#) PCTFRE

       42 CREATE INDEX I_ICOL1 ON ICOL$(OBJ#) PCTFREE 10 INI

       41 CREATE UNIQUE INDEX I_IND1 ON IND$(OBJ#) PCTFREE 1

       40 CREATE UNIQUE INDEX I_OBJ5 ON OBJ$(SPARE3,NAME,NAM

       39 CREATE INDEX I_OBJ4 ON OBJ$(DATAOBJ#,TYPE#,OWNER#)

       38 CREATE INDEX I_OBJ3 ON OBJ$(OID$) PCTFREE 10 INITR

       37 CREATE UNIQUE INDEX I_OBJ2 ON OBJ$(OWNER#,NAME,NAM

       36 CREATE UNIQUE INDEX I_OBJ1 ON OBJ$(OBJ#,OWNER#,TYP

       35 CREATE INDEX I_UNDO2 ON UNDO$(NAME) PCTFREE 10 INI

       34 CREATE UNIQUE INDEX I_UNDO1 ON UNDO$(US#) PCTFREE

       33 CREATE INDEX I_TAB1 ON TAB$(BOBJ#) PCTFREE 10 INIT

       32 CREATE TABLE CCOL$("CON#" NUMBER NOT NULL,"OBJ#"N

       31 CREATE TABLE CDEF$("CON#" NUMBER NOT NULL,"OBJ#"N

       30 CREATE INDEX I_COBJ# ON CLUSTER C_COBJ# PCTFREE 10

       29 CREATE CLUSTERC_COBJ#("OBJ#" NUMBER) PCTFREE 0 PC

       28 CREATE TABLE CON$("OWNER#" NUMBER NOT NULL,"NAME"

       27 CREATE UNIQUE INDEX I_PROXY_ROLE_DATA$_2 ON PROXY_

       26 CREATE INDEX I_PROXY_ROLE_DATA$_1 ON

       25 CREATE TABLE PROXY_ROLE_DATA$("CLIENT#" NUMBER

       24 CREATE UNIQUE INDEX I_PROXY_DATA$ ON PROXY_DATA$(C

       23 CREATE TABLE PROXY_DATA$("CLIENT#" NUMBER NOT NULL

       22 CREATE TABLE USER$("USER#" NUMBER NOT NULL,"NAME"

       21 CREATE TABLE COL$("OBJ#" NUMBER NOT NULL,"COL#"NU

       20 CREATE TABLE ICOL$("OBJ#" NUMBER NOT NULL,"BO#"NU

       19 CREATE TABLE IND$("OBJ#" NUMBER NOT NULL,"DATAOBJ#

       18 CREATE TABLE OBJ$("OBJ#" NUMBER NOT NULL,"DATAOBJ#

       17 CREATE TABLE FILE$("FILE#" NUMBER NOT NULL,"STATUS

       16 CREATE TABLE TS$("TS#" NUMBER NOT NULL,"NAME"VARC

       15 CREATE TABLE UNDO$("US#" NUMBER NOT NULL,"NAME"VA

       14 CREATE TABLE SEG$("FILE#" NUMBER NOTNULL,"BLOCK#"

       13 CREATE TABLE UET$("SEGFILE#" NUMBER NOT NULL,"SEGB

       12 CREATE TABLE FET$("TS#" NUMBER NOT NULL,"FILE#"NU

       11 CREATE INDEX I_USER# ON CLUSTER C_USER# PCTFREE 10

       10 CREATE CLUSTER C_USER#("USER#" NUMBER) PCTFREE 10

        9 CREATE INDEX I_FILE#_BLOCK# ON CLUSTER C_FILE#_BLO

         8 CREATE CLUSTERC_FILE#_BLOCK#("TS#" NUMBER,"SEGFIL

        7 CREATE INDEX I_TS# ON CLUSTER C_TS# PCTFREE 10 INI

        6 CREATE CLUSTER C_TS#("TS#" NUMBER) PCTFREE 10 PCTU

        5 CREATE TABLE CLU$("OBJ#" NUMBER NOT NULL,"DATAOBJ#

        4 CREATE TABLE TAB$("OBJ#" NUMBER NOT NULL,"DATAOBJ#

        3 CREATE INDEX I_OBJ# ON CLUSTER C_OBJ# PCTFREE 10 I

        2 CREATE CLUSTER C_OBJ#("OBJ#" NUMBER) PCTFREE 5 PCT

        0 CREATE ROLLBACK SEGMENT SYSTEM STORAGE (  INITIAL

       -1 8.0.0.0.0

60 rows selected.

SQL>

檢視一下Oracle 10g的bootstrap$:

SYS@anqing1(rac1)> select obj#,substr(sql_text,1,50) from bootstrap$ order by 1 desc;

     OBJ# SUBSTR(SQL_TEXT,1,50)

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

        56 CREATE TABLEBOOTSTRAP$("LINE#" NUMBER NOT NULL,"O

---- 注意這裡,在Oracle 10g 下面,這裡還是object_id還是56.

       55 CREATE UNIQUE INDEX I_CCOL2 ON CCOL$(CON#,INTCOL#)

       54 CREATE INDEX I_CCOL1 ON CCOL$(CON#,COL#) PCTFREE 1

       53 CREATE INDEX I_CDEF4 ON CDEF$(ENABLED) PCTFREE 10

       52 CREATE INDEX I_CDEF3 ON CDEF$(ROBJ#) PCTFREE 10 IN

       51 CREATE INDEX I_CDEF2 ON CDEF$(OBJ#) PCTFREE 10 INI

       50 CREATE UNIQUE INDEX I_CDEF1 ON CDEF$(CON#) PCTFREE

       49 CREATE UNIQUE INDEX I_CON2 ON CON$(CON#) PCTFREE 1

       48 CREATE UNIQUE INDEX I_CON1 ON CON$(OWNER#,NAME) PC

       47 CREATE UNIQUE INDEX I_COL3 ON COL$(OBJ#,INTCOL#) P

       46 CREATE INDEX I_COL2 ON COL$(OBJ#,COL#) PCTFREE 10

       45 CREATE UNIQUE INDEX I_COL1 ON COL$(OBJ#,NAME) PCTF

       44 CREATE UNIQUE INDEX I_USER1 ON USER$(NAME) PCTFREE

       43 CREATE UNIQUE INDEX I_TS1 ON TS$(NAME) PCTFREE 10

       42 CREATE UNIQUE INDEX I_FILE2 ON FILE$(TS#,RELFILE#)

       41 CREATE UNIQUE INDEX I_FILE1 ON FILE$(FILE#) PCTFRE

       40 CREATE INDEX I_ICOL1 ON ICOL$(OBJ#) PCTFREE 10 INI

       39 CREATE UNIQUE INDEX I_IND1 ON IND$(OBJ#) PCTFREE 1

       38 CREATE INDEX I_OBJ3 ON OBJ$(OID$) PCTFREE 10 INITR

       37 CREATE UNIQUE INDEX I_OBJ2 ON OBJ$(OWNER#,NAME,NAM

       36 CREATE UNIQUE INDEX I_OBJ1 ON OBJ$(OBJ#) PCTFREE 1

       35 CREATE INDEX I_UNDO2 ON UNDO$(NAME) PCTFREE 10 INI

       34 CREATE UNIQUE INDEX I_UNDO1 ON UNDO$(US#) PCTFREE

       33 CREATE INDEX I_TAB1 ON TAB$(BOBJ#) PCTFREE 10 INIT

       32 CREATE TABLECCOL$("CON#" NUMBER NOT NULL,"OBJ#" N

       31 CREATE TABLE CDEF$("CON#" NUMBER NOT NULL,"OBJ#"N

       30 CREATE INDEX I_COBJ# ON CLUSTER C_COBJ# PCTFREE 10

       29 CREATE CLUSTER C_COBJ#("OBJ#" NUMBER) PCTFREE 0 PC

       28 CREATE TABLE CON$("OWNER#" NUMBER NOT NULL,"NAME"

       27 CREATE UNIQUE INDEX I_PROXY_ROLE_DATA$_2 ON PROXY_

       26 CREATE INDEX I_PROXY_ROLE_DATA$_1 ON

       25 CREATE TABLE PROXY_ROLE_DATA$("CLIENT#" NUMBER

       24 CREATE UNIQUE INDEX I_PROXY_DATA$ ON PROXY_DATA$(C

       23 CREATE TABLE PROXY_DATA$("CLIENT#" NUMBER NOT NULL

       22 CREATE TABLE USER$("USER#" NUMBER NOT NULL,"NAME"

       21 CREATE TABLE COL$("OBJ#" NUMBER NOT NULL,"COL#"NU

       20 CREATE TABLE ICOL$("OBJ#" NUMBER NOT NULL,"BO#"NU

       19 CREATE TABLE IND$("OBJ#" NUMBER NOT NULL,"DATAOBJ#

       18 CREATE TABLE OBJ$("OBJ#" NUMBER NOT NULL,"DATAOBJ#

       17 CREATE TABLE FILE$("FILE#" NUMBER NOT NULL,"STATUS

       16 CREATE TABLE TS$("TS#" NUMBER NOT NULL,"NAME" VARC

       15 CREATE TABLE UNDO$("US#" NUMBER NOT NULL,"NAME"VA

       14 CREATE TABLE SEG$("FILE#" NUMBER NOTNULL,"BLOCK#"

       13 CREATE TABLE UET$("SEGFILE#" NUMBER NOT NULL,"SEGB

       12 CREATE TABLE FET$("TS#" NUMBER NOT NULL,"FILE#"NU

        11 CREATE INDEX I_USER# ON CLUSTER C_USER#PCTFREE 10

       10 CREATE CLUSTER C_USER#("USER#" NUMBER) PCTFREE 10

        9 CREATE INDEX I_FILE#_BLOCK# ON CLUSTER C_FILE#_BLO

        8 CREATE CLUSTER C_FILE#_BLOCK#("TS#" NUMBER,"SEGFIL

        7 CREATE INDEX I_TS# ON CLUSTER C_TS# PCTFREE 10 INI

        6 CREATE CLUSTER C_TS#("TS#" NUMBER) PCTFREE 10 PCTU

        5 CREATE TABLE CLU$("OBJ#" NUMBER NOT NULL,"DATAOBJ#

        4 CREATE TABLE TAB$("OBJ#" NUMBER NOT NULL,"DATAOBJ#

        3 CREATE INDEX I_OBJ# ON CLUSTER C_OBJ# PCTFREE 10 I

        2 CREATE CLUSTER C_OBJ#("OBJ#" NUMBER) PCTFREE 5 PCT

        0 CREATE ROLLBACK SEGMENT SYSTEM STORAGE (  INITIAL

       -1 8.0.0.0.0

57 rows selected.

二. Bootstrap$說明

根據我們第一小結的說明,這裡看一下資料庫OPEN的流程:

  在instance open 時,會讀取SYSTEM 表空間的datafile header,在這個Header中儲存了X$KCVFH 的資訊,這部分内容之前的blog 有說明:

​​Oracle 10g 中 X$KCVFH 說明​​

​​http://www.cndba.cn/dave/article/1348​​

       而X$KCVFH中的FHRDB字段指向了Root dba (bootstrap$), DSI 403 上對這個root dba的說明:

Root dba: Thisfield only occurs in data file #1, and is the location of blocks required duringbootstrapping the data dictionary (bootstrap$)。

在DB 從mount 到open的操作中,會先建立sys.bootstrap$ 表,該表包含了object_id 小于56(11g 小于59)的對象的DDL 語句,如OBJ$,C_OBJ$,TAB$等基表,然後全表掃描bootstrap$表,擷取這些DDL語句,最後在shared pool中建立這些對象。

現在我們來看一個問題,這些object_id 小于56的基表的定義到底存在什麼地方,因為實際上,這些object_id 的DDL 是在DB 建立時的sql.bsq 腳本建立的,然後将這些DDL 的定義存放在一個位置,在open時,會從這個位置讀取DDL 的定義然後插入到bootstrap$表。

Dbsnake 的blog 給了這個問題的答案:DDL 語句記錄到了ktetb[0]. Ktetbdba中。

當我們更新instance時,需要執行catupgrd.sql, 重新将這些DDL 語句刷到 ktetb[0]. Ktetbdba中。否則會報:ORA-00704 錯誤。

關于10g中的bootstrap$

​​http://dbsnake.com/2009/06/10g-bootstrap.html​​

Oracle rdba和 dba 說明

Oracle BBED 工具說明

​​http://www.cndba.cn/Dave/article/1466​​

Oracle bbed 五個實用示例

​​http://www.cndba.cn/Dave/article/1369​​

證明過程如下:

SQL> select * from bootstrap$ where obj#=0;

    LINE#       OBJ#

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

SQL_TEXT

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

        0          0

CREATE ROLLBACK SEGMENT SYSTEM STORAGE(  INITIAL 112K NEXT 56K MINEXTENTS 1 MAXEXTENTS 32765 OBJNO 0 EXTENTS (FILE 1 BLOCK 128))

這裡我們看到了objectid 為0的對象的DDL,是rollback segment。

将如下内容放到ultraEdit中,然後檢視其對應的十六進制:

CREATE ROLLBACK SEGMENT SYSTEM STORAGE(  INITIAL 112K NEXT 56K MINEXTENTS 1 MAXEXTENTS 32765 OBJNO 0 EXTENTS (FILE 1 BLOCK 128))

然後用BBED 工具dump  對應的block,來驗證一下:

dave:/home/oracle> bbed parfile=/u01/bbed.par

Password:

BBED: Release 2.0.0.0.0 - LimitedProduction on Mon Oct 31 15:50:21 2011

Copyright (c) 1982, 2007, Oracle.  All rights reserved.

************* !!! For Oracle Internal Useonly !!! ***************

BBED> set dba 1,377

       DBA             0x00400179(4194681 1,377)

BBED> show

       FILE#           1

       BLOCK#          377

       OFFSET          0

       DBA             0x00400179(4194681 1,377)

       FILENAME       /u01/app/oracle/oradata/anqing/system01.dbf

       BIFILE          bifile.bbd

       LISTFILE        /u01/filelist.txt

        BLOCKSIZE       8192

       MODE            Edit

       EDIT            Unrecoverable

       IBASE           Dec

       OBASE           Dec

       WIDTH           80

       COUNT           512

       LOGFILE         log.bbd

       SPOOL           No

BBED> p ktetb

struct ktetb[0], 8 bytes                    @108    

   ub4 ktetbdba                             @108      0x0040017a

  ub4 ktetbnbk                            @112      0x00000007

BBED>

SQL> SELECT DBMS_UTILITY.data_block_address_file (            

 2           TO_NUMBER(LTRIM('0x0040017a', '0x'),'xxxxxxxx'))

 3            AS file_no,

 4       DBMS_UTILITY.data_block_address_block (

 5           TO_NUMBER(LTRIM('0x0040017a', '0x'), 'xxxxxxxx'))

 6            AS block_no

 7    FROM DUAL;

  FILE_NO   BLOCK_NO

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

        1        378

 BBED> set dba 1,378

       DBA             0x0040017a(4194682 1,378)

BBED> set offset 8030

       OFFSET          8030

BBED> dump

 File: /u01/app/oracle/oradata/anqing/system01.dbf(1)

 Block: 378              Offsets: 8030 to 8191           Dba:0x0040017a

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

4352454154452052 4f4c4c42 41434b20 5345474d 454e5420

 53595354 454d2053 544f5241 47452028 2020494e49544941 4c203131 324b204e

 45585420 31303234 4b204d49 4e455854 454e54532031204d 41584558 54454e54

 53203332 37363520 4f424a4e 4f203020 455854454e545320 2846494c 45203120

 424c4f43 4b203929 292c0103033e6466 033e6466 09382e30 2e302e30 2e300106

 6101

 <32 bytes per line>

以上的結果和我們用UltraEdit 看到的一緻,由此可以确認bootstrap$裡儲存的DDL 對象的定語是儲存在ktetb[0]. Ktetbdba中。

三.對bootstrap$ 表進行DML 測試

       Bootstrap$裡儲存的都是系統的核心對象,我們可以直接對這個表進行修改,但因為啟動instance 會執行這裡面的内容,是以如果我們的修改的資訊不正确,那麼導緻的結果就是下次啟動時報ORA-600的錯誤。

在測試之前,我們先建立一個restore points,最後我們在復原回來。

​​Oracle FlashbackDatabase and Restore Points 說明​​

​​http://www.cndba.cn/dave/article/1349​​

3.1 建立restore points

SQL> startup mount;

ORACLE instance started.

Total System Global Area  377487360 bytes

Fixed Size                  1273804 bytes

Variable Size             155189300 bytes

Database Buffers          218103808 bytes

Redo Buffers                2920448 bytes

Database mounted.

SQL> create restore point bootstrap_before guarantee flashback database;

Restore point created.

SQL> alter database open;

Database altered.

3.2 對bootstrap$進行DML操作

先看一下bootstrap$的結構:

SQL> desc bootstrap$

 Name                                     Null?    Type

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

 LINE#                                     NOT NULLNUMBER

 OBJ#                                      NOT NULLNUMBER

 SQL_TEXT                                  NOT NULLVARCHAR2(4000)

SQL> select * from bootstrap$ where rownum=1;

    LINE#       OBJ# SQL_TEXT

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

       -1         -1 8.0.0.0.0

Bootstrap$ 有三個字段,啟動Line# 和 obj# 值相同,其中的obj# 是對象的ID,為了不破環現有的環境,我們先看一下系統中obj#的最大值:

SQL> select max(obj#) from obj$;

 MAX(OBJ#)

----------

    58903

SQL> Create table dave1 (id number);

Table created.

SQL> select max(obj#) from obj$;

 MAX(OBJ#)

----------

    58913

--注意這裡的對象ID,雖然我們隻建立了一個,但是在這個期間可能還有其他的對象被建立,我們在建立一個測試一次:

SQL> Create table dave2(id number);

Table created.

SQL> select max(obj#) from obj$;

 MAX(OBJ#)

----------

    58914

--這次obj# 隻加一個了。

現在我們insert 一條記錄到bootstrap$中:

SQL> insert into bootstrap$ values(100000,100000,'Dave test');

1 row created.

SQL> commit;

Commit complete.

SQL> select * from bootstrap$ where obj#=100000;

    LINE#       OBJ# SQL_TEXT

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

   100000     100000 Dave test

SQL> update bootstrap$ set sql_text='create table anqing(id number)' where obj#=100000; 

1 row updated.

SQL> commit;

Commit complete.

SQL> select * from bootstrap$ where obj#=100000;

    LINE#       OBJ# SQL_TEXT

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

   100000     100000 create tableanqing(id number)

SQL> select max(obj#) from obj$;

 MAX(OBJ#)

----------

    58914

這裡要注意,雖然我們insert 了一條記錄,但是真正的對象并沒有建立。

SQL> insert into bootstrap$ values(100000,100000,'create table anqing2(id number)');

1 row created.

SQL> commit;

Commit complete.

SQL> select * from bootstrap$ whereobj#=100000;

    LINE#       OBJ# SQL_TEXT

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

   100000     100000 create tableanqing(id number)

   100000     100000 create tableanqing2(id number)

我們删除一條記錄之後,重新開機我們執行個體,看看有什麼效果:

SQL> delete from bootstrap$ where sql_text='create table anqing2(id number)';

1 row deleted.

SQL> commit;

Commit complete.

SQL> select * from bootstrap$ where obj#=100000;

    LINE#       OBJ# SQL_TEXT

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

100000     100000 create table anqing(id number)

3.3重新開機執行個體

SQL> shutdown immediate

Database closed.

Database dismounted.

ORACLE instance shut down.

SQL> startup

ORACLE instance started.

Total System Global Area  377487360 bytes

Fixed Size                  1273804 bytes

Variable Size             155189300 bytes

Database Buffers          218103808 bytes

Redo Buffers                2920448 bytes

Database mounted.

ORA-01092: ORACLE instance terminated. Disconnectionforced

檢視alert log:

Mon Oct 31 17:28:33 CST 2011

Errors in file/u01/app/oracle/admin/anqing/udump/anqing_ora_8722.trc:

ORA-00600: internal errorcode, arguments: [16704], [100001], [], [], [], [], [], []

Mon Oct 31 17:28:33 CST 2011

Errors in file /u01/app/oracle/admin/anqing/udump/anqing_ora_8722.trc:

ORA-00704: bootstrapprocess failure

ORA-00600: internal error code, arguments:[16704], [100001], [], [], [], [], [], []

Mon Oct 31 17:28:33 CST 2011

Error 704 happened during db open, shuttingdown database

USER: terminating instance due to error 704

Instance terminated by USER, pid = 8722

ORA-1092 signalled during: ALTER DATABASEOPEN...

3.4 用restorepoint 将instance還原回來:

SQL> startup mount;

ORACLE instance started.

Total System Global Area  377487360 bytes

Fixed Size                  1273804 bytes

Variable Size             155189300 bytes

Database Buffers          218103808 bytes

Redo Buffers                2920448 bytes

Database mounted.

SQL> select open_mode,flashback_on from v$database;

OPEN_MODE FLASHBACK_ON

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

MOUNTED   RESTORE POINT ONLY

SQL> flashback database to restore point bootstrap_before;

Flashback complete.

SQL> alter database open resetlogs;

Database altered.

SQL> select * from bootstrap$ where obj#=100000;

no rows selected

這個例子雖然還原回來,但是也證明了一個問題,重新開機是一個危險的操作,是以重新開機需要慎重在謹慎,比如這裡的bootstrap$中的對象,可以進行修改,而且也不影響DB 的正常運作,但是一旦重新開機,那麼問題就會暴露出來。

四. 修改bootstrap$ 中的對象

       一般來說bootstrap$中的對象是不建議修改的,但是一些特殊情況下可能會用到,要注意的事,如果因為修改bootstrap$ 導緻的問題,Oracle 是不提供支援的。

在之前的Blog裡有介紹并修改過bootstrap$下的一個對象,參考:

​​Oracle 資料字典表 -- SYS.COL$​​

​​http://www.cndba.cn/Dave/article/1419​​

在MOS 上有一篇文章:

Size ofSys.C_obj#_intcol# cluster in system tablespace is growing [ID 463226.1]

這個案例将的是'SYS.C_OBJ#_INTCOL#' 占據了 90%的system 表空間,在MOS的這篇文檔裡隻是解釋了問什麼會占用這麼多空間。

而且給出的解決方案是重建資料庫,這個也就是說,oracle 不負責bootstrap$ 對象這部分的操作。雖然Oracle 說隻能重建DB,但是 oraclefans 還是提供了一種不重建DB來解決問題的方法,

根據白鳝的文章,在測試一次。感謝白鳝的幸苦勞動。

SQL> select obj# from obj$ where name='C_OBJ#_INTCOL#';

     OBJ#

----------

      251

SQL> SELECT OBJ#,NAME,TYPE# FROM OBJ$ WHERE DATAOBJ#=251;   

     OBJ# NAME                                TYPE#

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

      251 C_OBJ#_INTCOL#                          3

      253 HISTGRM$                                2

當我們進行truncate 的時候報錯:

SQL> truncate cluster c_obj#_intcol#;

truncate cluster c_obj#_intcol#

                 *

ERROR at line 1:

ORA-00701: object necessary forwarmstarting database cannot be altered

無法變更熱啟動資料庫所需的對象,即該對象是BOOTSTRAP$對象,是以無法TRUNCATE.

由于這個對象的ID是251,大于56, 是以該對象不是核心BOOTSTRAP$對象。

這裡可以利用EVENT 38003,EVENT 38003可以讓優化器認為這些非核心BOOTSTRAP對象不是BOOTSTRAP的,這樣我們就可以對這些對象進行設定該事件之前不能操作的操作了。

SQL> alter system set  EVENT="38003trace name context forever, level 10" scope=spfile;

System altered.

--該Event 需要重新開機才能生效

SQL> shutdown immediate

Database closed.

Database dismounted.

ORACLE instance shut down.

SQL> startup

ORACLE instance started.

Total System Global Area  377487360 bytes

Fixed Size                  1273804 bytes

Variable Size             155189300 bytes

Database Buffers          218103808 bytes

Redo Buffers                2920448 bytes

Database mounted.

Database opened.

SQL> truncate cluster c_obj#_intcol#;

Cluster truncated.

這次成功執行,不過因為這裡是對HISTGRM 進行的操作,是以最好重新分析一下表,否則影響執行計劃。

關閉event:

SQL> alter system set EVENT="38003trace name context forever off" scope=spfile;

System altered.

SQL> shutdown immediate

Database closed.

Database dismounted.

ORACLE instance shut down.

SQL> startup

ORA-02194: event specification syntax error230 (minor error 215) near 'OFF'

遇到小插曲了。 一看關閉event的文法寫錯了,多了一個forever,現在資料庫根本不能操作,連nomount都不行,不過幸運的是,我們可以直接修改pfile之後,在啟動。

SQL> create pfile from spfile;

File created.

修改pfile:

*.event='38003 trace name context foreveroff'

-->

*.event='38003 trace name context off'

SQL> create spfile from pfile='/u01/app/oracle/product/10.2.0/db_1/dbs/initanqing.ora';

File created.

SQL> startup

ORACLE instance started.

Total System Global Area  377487360 bytes

Fixed Size                  1273804 bytes

Variable Size             155189300 bytes

Database Buffers          218103808 bytes

Redo Buffers                2920448 bytes

Database mounted.

Database opened.

成功啟動了, 有關event的說明,參考:

​​Oracle 跟蹤事件 set event​​

​​http://www.cndba.cn/Dave/article/1215​​

最後還是那句話,對bootstrap$進行操作要慎重,如果迫不得已,也需要提前做好備份。

五.ORA-00704 錯誤說明

5.1 What is bootstrap process failure?ORA-00704

This ORA-00704 error SERIOUS if reported at startup. This error refers to some problem duringbootstrap operation.

Any ORA-00704error on STARTUP / RECOVER is serious, this error normally rosedue to someinconsistency with the bootstrap segments (or) datacorruption on bootstrap$ (or) any of the base tables below object_id 56. Afterthis error it might not allow to open that database.

ORA-00704 是一個非常嚴重的錯誤,一般當bootstrap$ 表發生錯誤或者bootstrap$ 包含的object_id 小于56的對象發生錯誤時,會報這種錯誤。遇到這種情況,如果有備份,可以進行恢複,如果沒有備份,可以嘗試用第四小節裡提到的EVENT 38003 來進行處理。

最後實在不行,還有一個工具可以嘗試:BBED。這些都是非正常的手法,要慎用。

5.2 When ORA-00704 shall occur?

1. There is aprobable of this error when any unsupported operations are tried to force openthe database.

2. This errorcan also occur when system datafile has corrupted blocks.(ORA-01578)

3. In earlierreleases of oracle (prior to 7.3.4 and 8.0.3) this issue shallarise due to Bug434596

The option is to restore it from a good backupand recover it.

-> If the underlying cause is physical corruption that is due to hardware problemsthen do complete recovery.

-> If the issue is not relating to any physical corruption, then the problemcould be due some unsupported actions on Bootstrap, and a Point In Time Recoverywould be an option in such case.

5.3 MOS 上的一個文檔

ORA-00704: Bootstrap Process Failure When10g Upgrade is Aborted [ID 427585.1]

Symptoms:

ORA-00704: bootstrap process failure

ORA-00604: error occurred at recursive SQL level 1

ORA-01406: fetched column value was truncated

Error 704 happened during db open, shutting down database

USER: terminating instance due to error 704

Instance terminated by USER, pid = 20971

ORA-1092 signalled during: ALTER DATABASE OPEN...

原因:

The bootstraperror failure happened since the upgrade process was abnormally terminated hence,the bootstrap Objects was corrupted and encountered with above errors。

這個案例比較簡單,因為更新過程失敗,導緻bootstrap object稱corrupted。

解決方法:

Restorea cold backup of the database from before the upgrade attempt was made and thenreaccomplish the upgrade。

從備份中恢複資料庫,然後重新進行更新。