从数据文件到内存的初始化过程:
SQL> startup mount
ORACLE 例程已经启动。
Total System Global Area 1970937856 bytes
Fixed Size 2191096 bytes
Variable Size 553648392 bytes
Database Buffers 1409286144 bytes
Redo Buffers 5812224 bytes
数据库装载完毕。
SQL> alter session set sql_trace=true;
会话已更改。
SQL> alter database open
2 /
数据库已更改。
SQL>
从跟踪文件中得到,首先创建bootstrap$表
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))
Oracle在启动时实际上是在内存中创建bootstrap$的结构,然后从数据文件的file 1 block 520读取数据到内存中,完成第一次初始化
查询 file 1 block 520上存储的是什么对象
SQL> selectsegment_name,file_id,block_id from dba_extents where block_id=520 andfile_id=1;
SEGMENT_NAME FILE_ID BLOCK_ID
------------------------------------------------------------------------------------------- ----------
BOOTSTRAP$ 1 520
发现存放的正是bootstrap$对象
Oracle进步一的操作是:
select line#, sql_text from bootstrap$where obj# != :1
在创建并从数据文件中装载了bootstrap$的内容之后,oracle开始递归地从该表中读取信息,加载数据,那么bootstrap$中记录的是什么信息呢:
在数据中,bootstrap$是实际存在的一张表
SQL> desc bootstrap$;
名称
--------------------------
LINE#
OBJ#
SQL_TEXT
通过:
Select * from bootstrap$ whererownum<10;
可以看到bootstrap$中实际上是记录一些数据库系统基本对象的创建语句,oracle通过bootstarp$进行向导,进一步创建相关的重要对象,从而启动数据库
定位bootstrap$
在系统表空间的root dba指向该对象
V10 STYLE FILE HEADER:
CompatibilityVsn = 186646528=0xb200000
DbID=1350043201=0x50780641, Db Name='ORCL'
ActivationID=0=0x0
ControlSeq=14000=0x36b0, File size=90880=0x16300
FileNumber=1, Blksiz=8192, File Type=3 DATA
Tablespace #0 - SYSTEM rel_fn:1
Creation at scn: 0x0000.0000000703/30/2010 10:07:48
Backup taken at scn: 0x0000.0000000001/01/1988 00:00:00 thread:0
reset logs count:0x3102bac5 scn:0x0000.000e74ff
prevreset logs count:0x2a9dfaf0 scn: 0x0000.00000001
recovered at 11/12/2013 15:48:51
status:0x2004 rootdba:0x00400208 chkpt cnt: 747 ctl cnt:746
begin-hot-backup file size: 0
Checkpointed at scn: 0x0000.003fca8d 11/12/2013 22:18:10
Root dba仅在系统表空间中存在,用于定位数据库引导的bootstarp$信息
SQL>
selectdbms_utility.data_block_address_file(to_number('400208','xxxxxxx')),dbms_utility.data_block_address_block(to_number('400208','xxxxxxx'))from dual;
得到file 1 block520
SQL> selectsegment_name,file_id,block_id from dba_extents where block_id=520 andfile_id=1;
SEGMENT_NAME FILE_ID BLOCK_ID
------------------------------------------------------------------------------------------- ----------
BOOTSTRAP$ 1 520
可以看到是bootstrap$对象
Bootstrap$对象中存放的就是创建这些对象的语句,这些语句在数据库启动时,需要被获取以在内存中创建这些对象,再从硬盘上加载启动数据必须的元数据从而启动数据库
通过10046事件可以跟踪一下数据库的启动过程
SQL> startup nomount
ORACLE 例程已经启动。
Total System Global Area 1970937856 bytes
Fixed Size 2191096 bytes
Variable Size 553648392 bytes
Database Buffers 1409286144 bytes
Redo Buffers 5812224 bytes
SQL> alter session set events='10046trace name context forever,level 12';
会话已更改。
SQL> alter database mount
2 /
数据库已更改。
SQL> alter database open
2 /
数据库已更改。
SQL>
*** 2013-11-19 09:23:22.205
WAIT #3: nam='SQL*Net message from client' ela=6875235 driver id=1413697536 #bytes=1 p3=0 obj#=-1 tim=4125009886
CLOSE#3:c=0,e=16,dep=0,type=1,tim=4125010120
XCTEND rlbk=0, rd_only=1, tim=4125010509
=====================
PARSING IN CURSOR #2 len=20 dep=0 uid=0oct=35 lid=0 tim=4125010946 hv=1913505115 ad='7ff73e08290'sqlid='fr02x8dt0vjav'
alter database mount
END OF STMT
PARSE#2:c=0,e=751,p=0,cr=0,cu=0,mis=1,r=0,dep=0,og=1,plh=0,tim=4125010945
WAIT #2: nam='rdbms ipc reply' ela= 556from_process=10 timeout=60 p3=0 obj#=-1 tim=4125013474
WAIT #2: nam='reliable message' ela= 1756channel context=8793729867568 channel handle=8793729769232 broadcastmessage=8793730870360 obj#=-1 tim=4125015484
………..
WAIT #3: nam='direct path read' ela= 6667file number=1 first dba=1 block cnt=1 obj#=-1 tim=4136878600
WAIT #3: nam='direct path read' ela= 15024file number=2 first dba=1 block cnt=1 obj#=-1 tim=4136893759
WAIT #3: nam='direct path read' ela= 11303file number=3 first dba=1 block cnt=1 obj#=-1 tim=4136905250
WAIT #3: nam='direct path read' ela= 40195file number=5 first dba=1 block cnt=1 obj#=-1 tim=4136945648
……..
WAIT #1: nam='db file sequential read' ela=204 file#=1 block#=520 blocks=1 obj#=59 tim=4138338313
…………..
WAIT #5: nam='db file sequential read' ela=17705 file#=1 block#=337 blocks=1 obj#=36 tim=4138435513
从以上信息可以注意到,oracle首先通过direct path read 方式从每个数据文件头读取了第一个block的信息,然后通过db file sequential read 的单块方式分别读取了数据文件1的第520个block和第337个block,第520个块正好存放是bootstrap$对象
找到bootstrap$对象,从而创建该对象
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))
再接下来创建在bootstrap$中记录的对象
注意:
System表空间损坏为什么会引起数据库无法启动,是因为system表空间中有root dba指向bootstrap$对象的,如果system表空间损坏就无法找到bootstrap$对象,从而无法创建其他对象,从而无法完成数据库初始化,所以数据库不能正常启动。