数据库的数据都存放在数据文件当中,当数据库开启时,Oracle怎么完成从数据文件读取数据到内存当中这个初始化过程呢?

SQL> startup mount;ORACLE instance started.Total System Global Area 6680915968 bytesFixed Size                  2213936 bytesVariable Size            3758098384 bytesDatabase Buffers         2885681152 bytesRedo Buffers               34922496 bytesDatabase mounted.SQL> alter session set sql_trace=true;SQL> alter database open;

通过上面的开启SQL跟踪参数后,启动数据的信息被记录在trace文件中,之前获取trace文件都是通过gettrcname.sql获取的,11G增加了一个新的视图可以直接获取到trace文件:

select value from v$diag_info where name = 'Default Trace File';VALUE--------------------------------------------------------------------/DBBK/oracle/diag/rdbms/orcl/orcl/trace/orcl_ora_22987.trc

如果直接去查看该文件,估计有点费劲,通过tkprof命令转换成人类可读的模式:

tkprof orcl_ora_22987.trc  1.trc

查看1.trc这个文件可以发现从开启SQL_TRACE开始记录的所有语句内容:

SQL ID: 4tk6t8tfsfqbfPlan Hash: 0alter session set sql_trace=truecall     count       cpu    elapsed       disk      query    current        rows------- ------  -------- ---------- ---------- ---------- ----------  ----------Parse        0      0.00       0.00          0          0          0           0Execute      1      0.00       0.00          0          0          0           0Fetch        0      0.00       0.00          0          0          0           0------- ------  -------- ---------- ---------- ---------- ----------  ----------total        1      0.00       0.00          0          0          0           0Misses in library cache during parse: 0Misses in library cache during execute: 1Optimizer mode: ALL_ROWSParsing user id: SYS......SQL ID: a01hp0psv0rrhPlan Hash: 0alter database opencall     count       cpu    elapsed       disk      query    current        rows------- ------  -------- ---------- ---------- ---------- ----------  ----------Parse        1      0.00       0.00          0          0          0           0Execute      1      0.32       1.45         19         34         63           0Fetch        0      0.00       0.00          0          0          0           0------- ------  -------- ---------- ---------- ---------- ----------  ----------total        2      0.32       1.45         19         34         63           0Misses in library cache during parse: 1Optimizer mode: ALL_ROWSParsing user id: SYS

从发出open语句后开始查看:

SQL ID: 32r4f1brckzq1Plan Hash: 0create 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))call     count       cpu    elapsed       disk      query    current        rows------- ------  -------- ---------- ---------- ---------- ----------  ----------Parse        1      0.00       0.00          0          0          0           0Execute      1      0.00       0.00          0          0          0           0Fetch        0      0.00       0.00          0          0          0           0------- ------  -------- ---------- ---------- ---------- ----------  ----------total        2      0.00       0.00          0          0          0           0Misses in library cache during parse: 1Optimizer mode: CHOOSEParsing user id: SYS   (recursive depth: 1)

这一步,Oracle在内存中创建了一个bootstrap$的表结构,并从file 1 block 520(数据文件1的520号块)内读取数据到该表中。

到这里我们可以查看一下file 1 block 520中记录的对象

SQL> select segment_name,file_id,block_id from dba_extents where file_id=1 and block_id=520;SEGMENT_NAME            FILE_ID   BLOCK_ID-------------------- ---------- ----------BOOTSTRAP$                    1        520

我们再来看看这张表中的字段和内容:

select line#,obj#,sql_text from bootstrap$;     LINE#       OBJ# SQL_TEXT---------- ---------- --------------------------------------------------        -1         -1 8.0.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))         2          2 CREATE CLUSTER C_OBJ#("OBJ#" NUMBER) PCTFREE 5 PCT                      USED 40 INITRANS 2 MAXTRANS 255 STORAGE (  INITIAL                       136K NEXT 200K MINEXTENTS 1 MAXEXTENTS 2147483645                       PCTINCREASE 0 OBJNO 2 EXTENTS (FILE 1 BLOCK 144))                       SIZE 800         3          3 CREATE INDEX I_OBJ# ON CLUSTER C_OBJ# PCTFREE 10 I                      NITRANS 2 MAXTRANS 255 STORAGE (  INITIAL 64K NEXT                       1024K MINEXTENTS 1 MAXEXTENTS 2147483645 PCTINCRE                      ASE 0 OBJNO 3 EXTENTS (FILE 1 BLOCK 168))         4          4 CREATE TABLE TAB$("OBJ#" NUMBER NOT NULL,"DATAOBJ#                      " NUMBER,"TS#" NUMBER NOT NULL,"FILE#" NUMBER NOT                      NULL,"BLOCK#" NUMBER NOT NULL,"BOBJ#" NUMBER,"TAB#                      " NUMBER,"COLS" NUMBER NOT NULL,"CLUCOLS" NUMBER,"                      PCTFREE$" NUMBER NOT NULL,"PCTUSED$" NUMBER NOT NU                      LL,"INITRANS" NUMBER NOT NULL,"MAXTRANS" NUMBER NO                      T NULL,"FLAGS" NUMBER NOT NULL,"AUDIT$" VARCHAR2(3                      8) NOT NULL,"ROWCNT" NUMBER,"BLKCNT" NUMBER,"EMPCN                      T" NUMBER,"AVGSPC" NUMBER,"CHNCNT" NUMBER,"AVGRLN"                       NUMBER,"AVGSPC_FLB" NUMBER,"FLBCNT" NUMBER,"ANALY                      ZETIME" DATE,"SAMPLESIZE" NUMBER,"DEGREE" NUMBER,"                      INSTANCES" NUMBER,"INTCOLS" NUMBER NOT NULL,"KERNE                      LCOLS" NUMBER NOT NULL,"PROPERTY" NUMBER NOT NULL,                      "TRIGFLAG" NUMBER,"SPARE1" NUMBER,"SPARE2" NUMBER,                      "SPARE3" NUMBER,"SPARE4" VARCHAR2(1000),"SPARE5" V                      ARCHAR2(1000),"SPARE6" DATE) STORAGE (  OBJNO 4 TA                      BNO 1) CLUSTER C_OBJ#(OBJ#)         5          5 CREATE TABLE CLU$("OBJ#" NUMBER NOT NULL,"DATAOBJ#                      " NUMBER,"TS#" NUMBER NOT NULL,"FILE#" NUMBER NOT                      NULL,"BLOCK#" NUMBER NOT NULL,"COLS" NUMBER NOT NU                      LL,"PCTFREE$" NUMBER NOT NULL,"PCTUSED$" NUMBER NO                      T NULL,"INITRANS" NUMBER NOT NULL,"MAXTRANS" NUMBE                      R NOT NULL,"SIZE$" NUMBER,"HASHFUNC" VARCHAR2(30),                      "HASHKEYS" NUMBER,"FUNC" NUMBER,"EXTIND" NUMBER,"F                      LAGS" NUMBER,"DEGREE" NUMBER,"INSTANCES" NUMBER,"A                      VGCHN" NUMBER,"SPARE1" NUMBER,"SPARE2" NUMBER,"SPA                      RE3" NUMBER,"SPARE4" NUMBER,"SPARE5" VARCHAR2(1000                      ),"SPARE6" VARCHAR2(1000),"SPARE7" DATE) STORAGE (                        OBJNO 5 TABNO 2) CLUSTER C_OBJ#(OBJ#)......

可以看到该表中又包含了其它创建在内容中的对象,到这里,我们回过头来看SQL_TRACE文件:

SQL ID: 6apq2rjyxmxpjPlan Hash: 867914364select line#, sql_textfrom bootstrap$ where obj# != :1call     count       cpu    elapsed       disk      query    current        rows------- ------  -------- ---------- ---------- ---------- ----------  ----------Parse        1      0.00       0.00          0          0          0           0Execute      1      0.00       0.00          0          0          0           0Fetch       60      0.00       0.00          4         61          0          59------- ------  -------- ---------- ---------- ---------- ----------  ----------total       62      0.00       0.00          4         61          0          59Misses in library cache during parse: 1Misses in library cache during execute: 1Optimizer mode: CHOOSEParsing user id: SYS   (recursive depth: 1)Rows     Row Source Operation-------  ---------------------------------------------------     59  TABLE ACCESS FULL BOOTSTRAP$ (cr=61 pr=4 pw=0 time=0 us)********************************************************************************SQL ID: 864bmh11c121aPlan Hash: 0CREATE ROLLBACK SEGMENT SYSTEM STORAGE (  INITIAL 112K NEXT 56K MINEXTENTS 1  MAXEXTENTS 32765 OBJNO 0 EXTENTS (FILE 1 BLOCK 128))call     count       cpu    elapsed       disk      query    current        rows------- ------  -------- ---------- ---------- ---------- ----------  ----------Parse        1      0.00       0.00          0          0          0           0Execute      1      0.00       0.00          0          0          0           0Fetch        0      0.00       0.00          0          0          0           0------- ------  -------- ---------- ---------- ---------- ----------  ----------total        2      0.00       0.00          0          0          0           0Misses in library cache during parse: 1Optimizer mode: CHOOSEParsing user id: SYS   (recursive depth: 1)......

到这里我想,大家大概就能看懂了,跟我刚才查看bootstrap$一样,数据库去查找该表中的内容,逐一运行 (:1是系统给定的变量,估计该变量值为1)。

即:Oracle启动先将Bootstrap$加载到内存中,随后逐一将数据初始化所需的对象加载到内存中,在BootStrap$表中的对象,每一个都值得研究,这里暂时不详细说明。

 

通过上述说明,可以看出bootstrap$的重要性,当然在书中还做了一个小测试,就是改动该表中的内容,看看对数据库启动是否造成影响(轻易不要做这样的测试,做之前最好备份数据库,当然这个测试也是可以恢复的):

SQL> update bootstrap$ set sql_text='9.0.0.1.0' where obj#=-1;1 row updated.SQL> select line#,obj#,sql_text from bootstrap$ where obj#=-1 order by obj#;     LINE#       OBJ# SQL_TEXT---------- ---------- --------------------------------------------------        -1         -1 9.0.0.1.0SQL> commit;Commit complete.SQL> shutdown immediate;SQL> startup;ORACLE instance started.Total System Global Area 6680915968 bytesFixed Size                  2213936 bytesVariable Size            3758098384 bytesDatabase Buffers         2885681152 bytesRedo Buffers               34922496 bytesDatabase mounted.ORA-01092: ORACLE instance terminated. Disconnection forcedORA-00704: bootstrap process failureORA-00702: bootstrap verison '9.0.0.1.0' inconsistent with version '8.0.0.0.0'Process ID: 4883Session ID: 96 Serial number: 3

可以看到数据库mount没问题,但open的时候读取bootstrap$报错,错误内容页写的很清楚,处理bootstrap$失败,版本号不一致。所以对于这类问题的解决方式,最好是时长对数据库进行备份,当问题发生时进行不完全恢复。

 

通过Oracle自带工具BBED(BLOCK BROWSER/EDITOR)工具进行恢复(关于BBED的工具的编译安装,我的博客中有记载:,这里不详细介绍)

增加配置文件:

指定块大小,修改模式和BBED连接数据文件列表[oracle@021Y-SH-BKAP oracle]$ cat par.bbd blocksize=8192listfile=file.lstmode=edit指定文件列表中的数据文件格式: 数据文件号 路径 大小[oracle@021Y-SH-BKAP oracle]$ cat file.lst 1 /DBBK/oracle/oradata/orcl/system01.dbf 723525632用bbed工具访上面的参数文件(BBED默认密码blockedit)[oracle@021Y-SH-BKAP oracle]$ bbed parfile=par.bbd Password: *********

 

进行如下操作,因为我们已知了bootstrap是存放在file 1 block 520上的(我这里有点犯傻,就一直在该块和前面的块找改动的内容,实际记录的内容应该向后移动一个块):

BBED: Release 2.0.0.0.0 - Limited Production on Thu Jan 15 15:56:23 2015Copyright (c) 1982, 2009, Oracle and/or its affiliates.  All rights reserved.************* !!! For Oracle Internal Use only !!! ***************BBED> set dba 1,521 offset 0        DBA             0x00400209 (4194825 1,521)        OFFSET          0

 定位被自己修改的内容(关键要找到内容所在的块)

BBED> find /c 9.0.0.1.0 File: /DBBK/oracle/oradata/orcl/system01.dbf (1) Block: 521              Offsets: 8181 to 8191           Dba:0x00400209---------------------------------------------------------------------- 302e302e 312e3002 0676c9

 这里用的是ASCII码,显示的内容明显为0.0.1.0 结果不正确,应该向前偏移2个单位

BBED> dump /v dba 1,521 offset 8179 count 11 File: /DBBK/oracle/oradata/orcl/system01.dbf (1) Block: 521     Offsets: 8179 to 8189  Dba:0x00400209------------------------------------------------------- 392e302e 302e312e 300206            l 9.0.0.1.0..

修改该内容,恢复为8.0.0.0.0

BBED> modify /c '8.0.0.0.0' dba 1,521 offset 8179 File: /DBBK/oracle/oradata/orcl/system01.dbf (1) Block: 521              Offsets: 8179 to 8189           Dba:0x00400209------------------------------------------------------------------------ 382e302e 302e302e 300206BBED> dump /v dba 1,521 offset 8179 count 11 File: /DBBK/oracle/oradata/orcl/system01.dbf (1) Block: 521     Offsets: 8179 to 8189  Dba:0x00400209------------------------------------------------------- 382e302e 302e302e 300206            l 8.0.0.0.0.. <16 bytes per line>BBED> sum dba 1,521 applyCheck value for File 1, Block 521:current = 0x5f51, required = 0x5f51

应用后可以看到current的值与required的值相同。再次启动正常:

SQL> startup ORACLE instance started.Total System Global Area 6680915968 bytesFixed Size                  2213936 bytesVariable Size            3758098384 bytesDatabase Buffers         2885681152 bytesRedo Buffers               34922496 bytesDatabase mounted.Database opened.

 

参考:

           

            《DBA入门,诊断与进阶案例》 盖国强著