oracle中的open,oracle open阶段初始化理解

数据库启动研究:

oracle启动时候,首先需要在内存中创建数据库初始化的结构,然后把数据文件中与初始化相关的内容读入这个结构,进而执行这些内容,这个初始化的结构就是bootstraps$,这些内容就是bootstraps$表中的sql语句。

实验分析:

1. 打开sql跟踪

SYS AS SYSDBA >startup mount;

SYS AS SYSDBA >alter session set sql_trace = true;

SYS AS SYSDBA >alter database open;

SYS AS SYSDBA >col name for a20

SYS AS SYSDBA >col value for a50

2. 查看跟踪文件:

SYS AS SYSDBA >select * from v$diag_info where NAME='Default Trace File';

INST_ID|NAME                |VALUE

----------|--------------------|--------------------------------------------------

1|Default Trace File  |/u01/diag/rdbms/hx/hx/trace/hx_ora_10720.trc

3. 格式化跟踪文件: SYS AS SYSDBA >show parameter timed_stat;

NAME                                |TYPE       |VALUE

------------------------------------|-----------|------------------------------

timed_statistics                    |boolean    |TRUE

SYS AS SYSDBA >show parameter dump_file_size;

NAME                                |TYPE       |VALUE

------------------------------------|-----------|------------------------------

max_dump_file_size                  |string     |unlimited

SYS AS SYSDBA >show parameter  user_dump;

NAME                                |TYPE       |VALUE

------------------------------------|-----------|------------------------------

user_dump_dest                      |string     |/u01/diag/rdbms/hx/hx/trace

tkprof格式转换:

tkprof  hx_ora_10634.sql  hx_ora_10634.txt

4. 读取文件hx_ora_10634.txt,分析初始化过程:

********************************************************************************

SQL ID: 32r4f1brckzq1 Plan Hash: 0

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))

上面是第一个sql,可以看到,oracle在内存中创建这个表结构,数据是从file 1 block 520开始读取并加载的

看看file 1 block 520存放了哪个段的内容:

SYS AS SYSDBA >select SEGMENT_NAME,FILE_ID,BLOCK_ID,TABLESPACE_NAME from

dba_extents where file_id=1 and block_id=520;

SEGMENT_NAME             |   FILE_ID|  BLOCK_ID|TABLESPACE_NAME

-------------------------|----------|----------|--------------------

BOOTSTRAP$               |         1|       520|SYSTEM

SYS AS SYSDBA >select SEGMENT_NAME,FILE_ID,BLOCK_ID,blocks,TABLESPACE_NAME from dba_extents where SEGMENT_NAME='BOOTSTRAP$';

SEGMENT_NAME             |   FILE_ID|  BLOCK_ID|    BLOCKS|TABLESPACE_NAME

-------------------------|----------|----------|----------|--------------------

BOOTSTRAP$               |         1|       520|         8|SYSTEM            |         1|       520|SYSTEM

这个块存放的就是表BOOTSTRAP$的头块,这个表仅仅占用了一个区间。

继续跟踪文件:

********************************************************************************

SQL ID: 6apq2rjyxmxpj Plan Hash: 867914364

select line#, sql_text

from

bootstrap$ where obj# != :1

从上面看到,oracle在装载file 1 block 520后,就开始从这个表读取内容,实际上读取的是一些sql语句,然后利用这些sql语句创建数据库启动的必要对象:

SYS AS SYSDBA >select line#,obj#,sql_text from bootstrap$ where rownum<=3;

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))

20|        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|        42|CREATE INDEX I_ICOL1 ON ICOL$(OBJ#) PCTFREE 10 INITRANS 2 MAXTRANS 255 STORAGE (  INITIAL 64K NEXT 1

|          |024K MINEXTENTS 1 MAXEXTENTS 2147483645 PCTINCREASE 0 OBJNO 42 EXTENTS (FILE 1 BLOCK 384))

通过跟踪文件,可以看到,就是在执行这些语句:

CREATE ROLLBACK SEGMENT SYSTEM STORAGE (  INITIAL 112K NEXT 56K MINEXTENTS 1

MAXEXTENTS 32765 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 MINEXTENTS 1 MAXEXTENTS 2147483645

PCTINCREASE 0 OBJNO 2 EXTENTS (FILE 1 BLOCK 144)) SIZE 800

********************************************************************************

CREATE INDEX I_OBJ# ON CLUSTER C_OBJ# PCTFREE 10 INITRANS 2 MAXTRANS 255

STORAGE (  INITIAL 64K NEXT 1024K MINEXTENTS 1 MAXEXTENTS 2147483645

PCTINCREASE 0 OBJNO 3 EXTENTS (FILE 1 BLOCK 168))                                                                 ………………………………………………………………………………………………………………………………………………………………

5. bootstrap$的生成与定位

那么,数据文件中的 bootstrap$是怎么生成的呢?那就要归功于创建数据库时候的sql.bsp文件了。隐含参数记录了这个文件:

SYS AS SYSDBA >col ksppinm for a20

col ksppdesc for a40

col ksppstvl for a10

select  ksppinm,ksppdesc,ksppstvl

from sys.x$ksppi x,sys.x$ksppcv y

where   x.inst_id = userenv('Instance') and  y.inst_id = userenv('Instance') and  x.indx = y.indx and  (x.ksppinm like '%&par%');

/

Enter value for par: init_sql

old   3: where   x.inst_id = userenv('Instance') and  y.inst_id = userenv('Instance') and  x.indx = y.indx and  (x.ksppinm like '%&par%')

new   3: where   x.inst_id = userenv('Instance') and  y.inst_id = userenv('Instance') and  x.indx = y.indx and  (x.ksppinm like '%init_sql%')

KSPPINM             |KSPPDESC                                |KSPPSTVL

--------------------|----------------------------------------|----------

_init_sql_file      |File containing SQL statements to execut|?/rdbms/ad

|e upon database creation                |min/sql.bs

|                                        |q

创建数据库的create database语句隐含就要执行sql.bsp中的内容,这个文件包含了许多个bsp文件,其中的dcore.bsq文件就有表bootstrap$的创建语句。

create table bootstrap$

( line#         number not null,                       /* statement order id */

obj#          number not null,                            /* object number */

sql_text      varchar2("M_VCSZ") not null)                    /* statement */

storage (initial 50K)            /* to avoid space management during IOR I */

//

/* "//" required for bootstrap */

通过上面的分析,数据库在内存中建立表结构后,直接定位到file 1 block 520,从而继续后面的工作。那么,他怎么知道是这个块是bootstrap$段的头块呢?那就要看system表空间记录的root dba了。

6  root dba 相关

system表空间的数据文件头记录了这个东西:

转存system表空间一号数据文件头看看:

10 STYLE FILE HEADER:

Compatibility Vsn = 186646528=0xb200000

Db ID=763100300=0x2d7bfc8c, Db Name='HX'

Activation ID=0=0x0

Control Seq=14715=0x397b, File size=51200=0xc800

File Number=1, Blksiz=8192, File Type=3 DATA

Tablespace #0 - SYSTEM  rel_fn:1

Creation   at   scn: 0x0000.00000009 02/06/2013 17:15:16

Backup taken at scn: 0x0000.000cec73 03/31/2013 21:44:20 thread:1

reset logs count:0x30817c6a scn: 0x0000.003cef48

prev reset logs count:0x305eefc2 scn: 0x0000.000c7def

recovered at 05/12/2013 22:15:57

status:0x2004 root dba:0x00400208 chkpt cnt: 1095 ctl cnt:1094

begin-hot-backup file size: 41600

Checkpointed at scn:  0x0000.0054c1ba 05/13/2013 20:02:02

thread:1 rba:(0xa2.4d1e.10)

注意:只有system表空间的文件头才具备root dba,root dba只存在于system表空间的文件头中,用来定位数据库引导的bootstrap$信息。root dba一共4字节。

root dba(0x00400208)转换为2进制:0000000001 0000000000001000001000,前面10位表示文件号,就是1(/u01/oradata/hx/system01.dbf),后面22位表示数据文件1上的第520个块。

函数转换root dba(eygle大师的脚本):

SYS AS SYSDBA >CREATE OR REPLACE FUNCTION getbfno (p_dba IN VARCHAR2)

2       RETURN VARCHAR2

3    IS

4       l_str   VARCHAR2 (255) DEFAULT NULL;

5    BEGIN

6       l_str :=

7             'datafile# is:'

8          || DBMS_UTILITY.data_block_address_file

9  (TO_NUMBER (LTRIM (p_dba, '0x'),'xxxxxxxx'))

10          || chr(10)||'datablock is:'

11          || DBMS_UTILITY.data_block_address_block

12  (TO_NUMBER (LTRIM (p_dba, '0x'),'xxxxxxxx'));

13       RETURN l_str;

14    END;

15    /

col bfno for a20

Function created.

SYS AS SYSDBA >select getbfno('&a') bfno from dual;

Enter value for a: 00400208

old   1: select getbfno('&a') bfno from dual

new   1: select getbfno('00400208') bfno from dual

BFNO

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

datafile# is:1

datablock is:520

不同版本数据库中root dba 块的意义:

通过下面sql语句,可以看到头块为520之前的对象。

SYS AS SYSDBA >select b.object_id,a.segment_name,a.segment_type,a.header_block from dba_segments a,dba_objects b where

a.segment_name=b.object_name(+) and a.header_file=1 and a.header_block<=520 order by a.header_block;

SYS AS SYSDBA >select b.object_id,a.segment_name,a.segment_type,a.header_block from dba_segments a,dba_objects b where

a.segment_name=b.object_name(+) and a.header_file=1 and a.header_block<=520 order by a.header_block;

OBJECT_ID|SEGMENT_NAME             |SEGMENT_TYPE      |HEADER_BLOCK

----------|-------------------------|------------------|------------

|SYSTEM                   |ROLLBACK          |         128

2|C_OBJ#                   |CLUSTER           |         144

3|I_OBJ#                   |INDEX             |         168

6|C_TS#                    |CLUSTER           |         176

7|I_TS#                    |INDEX             |         184

8|C_FILE#_BLOCK#           |CLUSTER           |         192

9|I_FILE#_BLOCK#           |INDEX             |         200

10|C_USER#                  |CLUSTER           |         208

11|I_USER#                  |INDEX             |         216

15|UNDO$                    |TABLE             |         224

17|FILE$                    |TABLE             |         232

18|OBJ$                     |TABLE             |         240

23|PROXY_DATA$              |TABLE             |         248

24|I_PROXY_DATA$            |INDEX             |         256

25|PROXY_ROLE_DATA$         |TABLE             |         264

26|I_PROXY_ROLE_DATA$_1     |INDEX             |         272

27|I_PROXY_ROLE_DATA$_2     |INDEX             |         280

28|CON$                     |TABLE             |         288

29|C_COBJ#                  |CLUSTER           |         296

30|I_COBJ#                  |INDEX             |         304

33|I_TAB1                   |INDEX             |         312

34|I_UNDO1                  |INDEX             |         320

35|I_UNDO2                  |INDEX             |         328

36|I_OBJ1                   |INDEX             |         336

37|I_OBJ2                   |INDEX             |         344

38|I_OBJ3                   |INDEX             |         352

39|I_OBJ4                   |INDEX             |         360

40|I_OBJ5                   |INDEX             |         368

41|I_IND1                   |INDEX             |         376

42|I_ICOL1                  |INDEX             |         384

43|I_FILE1                  |INDEX             |         392

44|I_FILE2                  |INDEX             |         400

45|I_TS1                    |INDEX             |         408

46|I_USER1                  |INDEX             |         416

47|I_USER2                  |INDEX             |         424

48|I_COL1                   |INDEX             |         432

49|I_COL2                   |INDEX             |         440

50|I_COL3                   |INDEX             |         448

51|I_CON1                   |INDEX             |         456

52|I_CON2                   |INDEX             |         464

53|I_CDEF1                  |INDEX             |         472

54|I_CDEF2                  |INDEX             |         480

55|I_CDEF3                  |INDEX             |         488

56|I_CDEF4                  |INDEX             |         496

57|I_CCOL1                  |INDEX             |         504

58|I_CCOL2                  |INDEX             |         512

59|BOOTSTRAP$               |TABLE             |         520

从上图,对比之前bootstrap$中的sql语句,可以看到,520之前的块都和数据库启动相关。

在oracle 10g和11g中,520块正好就是bootstrap$的头块,可以转储这个块分析:

alter system dump datafile 1 block 520;

frmt: 0x02 chkval: 0xe443 type: 0x10=DATA SEGMENT HEADER - UNLIMITED

……………………………………………………………………………………………………………………………………………………………………………………

Extent Control Header

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

Extent Header:: spare1: 0      spare2: 0      #extents: 1      #blocks: 7

last map  0x00000000  #maps: 0      offset: 4128

Highwater::  0x0040020c  ext#: 0      blk#: 3      ext size: 7

#blocks in seg. hdr's freelists: 1

#blocks below: 3

mapblk  0x00000000  offset: 0

Unlocked

Map Header:: next  0x00000000  #extents: 1    obj#: 59     flag: 0x40000000

Extent Map

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

0x00400209  length: 7

nfl = 1, nfb = 1 typ = 1 nxf = 0 ccnt = 3

SEG LST:: flg: USED   lhd: 0x0040020b ltl: 0x0040020b

可以看到,这个块是obj#:=59的对象的头块,实际就是bootstrap$,以后的7个块(从0x00400209 开始,即521号块开始)都是bootstrap中存储的内容(当然,这些内容就是创建那些对象的sql语句了)。 简单的说,520号块类似一级位图块。

如果是oracle9i,第520号块存储的应该是一个cache,这个cache并不直接存放bootstrap$的内容,它类似二级位图块,指向bootstrap$的头块。

7.结论:oracle open阶段初始化的时候,要做下面几件事(10g or 11g):

1. 在内存中创建bootstraps$结构

1. 读system表空间中的1号文件的数据文件头中记录的root dba(实际就是bootstrap$的头块)

2. 通过root dba定位到bootstrap$

3. 把bootstrap$表中的数据装载到内存中的bootstraps$

4. 执行bootstrap$中的sql语句,创建一系列的数据字典

5. 打开数据库,有冤报冤,有仇报仇

524bbc790290d6bff1c59e86d5fe1a13.gif

思考:

1.oracle为什么要这样初始化数据库呢?

2.bootstraps$之前的段空间管理技术是否普通表空间的管理技术是否一样?如果不一样,有什么异同?

3.oracle 10g和11g中,bootstraps$的头块是否可以看作是三级位图块,特殊段头?

4.初始化时候,创建的那些对象分别是干什么的?这个可以适当研究下。

5.初始化时候,那个rollback对象有什么特殊性么?

6.数据库open完成之前,就可以对数据文件进行写操作?否则创建的那些对象难道存在于内存中?数据库关闭后那些对象是否还存在?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值