数据库初始化过程

时间:2021-08-16 19:51:41

从数据文件到内存的初始化过程:

 

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$对象,从而无法创建其他对象,从而无法完成数据库初始化,所以数据库不能正常启动。