|
对于这个问题我认为是论证不够充分,因为不能凭trace文件中的create语句中segment包含文件号和块号就断定说bootstrap$表头部是位于固定的地方于是数据库能够判断
到底从哪里开始找到其他的数据字典表,从而找到所有的其他存储对象。
请看我的测试:
10gr2+linux
其实有很多的dba都知道在$ORACLE_HOME/rdbms/admin下有一个sql.bsq的文件,对于这个文件的作用,就是在创建数据库(create database)时会执行的一个sql文件,这个
文件包含了创建基本数据字典表的相关sql。可以查看这个sql会发现创建bootstrap$,tab$等等的sql。可以发现在这个文件中所有的建表/cluster/索引的sql都没有指定
所处的头部文件号和块号(再说oracle也不支持这样的sql写法),有的存储参数是一些initial /next /size等等的参数。所以很有可能在这样的sql执行中并不能保证所建立的
表格从哪个文件哪个块开始(想象一下,不同的块大小的设定,就会对inittial/next等相同的参数使用不同的起头块)。
那从哪里可以看出来在创建数据库时会执行这个文件?这是由参数_init_sql_file来指定的。一个没有修改过的参数文件,隐含参数_init_sql_file的值如下:
sys@ORA920> select * from small_parameters where name='_init_sql_file';
NAME TYPE VALUE ISDEFAULT
-------------------- ---- ---------------------------------------- ---------
_init_sql_file 2 $ORACLE_HOME$/rdbms/admin/sql.bsq TRUE
(small_parameters是我创建的一个可以显示所有参数的试图)
那再追究这个参数的缺省值写在哪里,我通过这样的方式找到了缺省值:
在oracle应用程序里面包含了参数的缺省值(或者说程序里面已经写死了先,它能够引用环境变量,然后初始化参数可以覆盖它):
[oracle@db31 bin]$ strings oracle|grep _init_sql_file
_init_sql_file
[oracle@db31 bin]$ strings oracle> /tmp/oracle.txt
[oracle@db31 bin]$ vi /tmp/oracle.txt
...
_init_sql_file
?/rdbms/admin/sql.bsq
optimizer_features_enable
optimizer plan compatibility parameter
fixed_date
fixed SYSDATE value
audit_trail
enable system auditing
其他的一些缺省值也可以在这里看到。
再参考http://www.ixora.com.au/tips/cre ... 且可以发现bootstrap$不是第一个创建的对象,所以
可以测试一下,通过修改存储参数是否会影响bootstrap$的起始块。
我做了两种测试,第一、在bootstrap$表前面创建一个自己定义的表,可以发现在创建数据库的时候会发现报错(好像是报不存在的表格,很好;我没有再测试把后面的表提到
前面来创建,估计这还是很可能可行的,这样也很可能影响后面表格的头块位置),没有办法创建这张表;
第二,修改一些存储参数(加大N倍!),通过修改位于bootstrap$前面的cluster的存储参数,可以发现可以创建数据库,
这也验证了http://www.ixora.com.au/tips/creation/bsq.htm中的说明。
然后来比较一下两种情况下的数据库open是的trace文件,就会发现起始块发生了变化。
修改sql.bsq前的数据库:
ALTER DATABASE OPEN
END OF STMT
PARSE #1:c=0,e=577,p=0,cr=0,cu=0,mis=1,r=0,dep=0,og=1,tim=1128456747311595
=====================
PARSING IN CURSOR #2 len=188 dep=1 uid=0 oct=1 lid=0 tim=1128456747767489 hv=1365064427 ad='3074815c'
create table bootstrap$ ( line# number not null, obj# number not null, sql_text varchar2(4000) not null) storage (initial 50K objno 56 extents (file 1 block 377))
END OF STMT
PARSE #2:c=0,e=106986,p=0,cr=0,cu=0,mis=1,r=0,dep=1,og=4,tim=1128456747767480
EXEC #2:c=0,e=24605,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,tim=1128456747792212
修改sql.bsq后的数据库:
ALTER DATABASE OPEN
END OF STMT
PARSE #1:c=0,e=780,p=0,cr=0,cu=0,mis=1,r=0,dep=0,og=1,tim=1128458975177406
=====================
PARSING IN CURSOR #2 len=188 dep=1 uid=0 oct=1 lid=0 tim=1128458975448861 hv=3224480348 ad='30748164'
create table bootstrap$ ( line# number not null, obj# number not null, sql_text varchar2(4000) not null) storage (initial 50K objno 56 extents (file 1 block 633))
END OF STMT
PARSE #2:c=0,e=619,p=0,cr=0,cu=0,mis=1,r=0,dep=1,og=4,tim=1128458975448854
EXEC #2:c=0,e=229,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,tim=1128458975449199
通过查看数据字典也可以发现这样的变化。
从上面的分析可以至少可以得到这样的结论:
1、数据库创建时会执行_init_sql_file参数指定的创建数据字典文件,通常这个文件是$ORACLE_HOME/rdbms/admin/sql.bsq。并可以有限度的修改这个文件(我只测试成功了
修改一些存储参数);
2、bootstrap$头块不是创建在固定文件固定块位置的,它会受到sql.bsq中存储参数和数据块大小的影响,所以对于oracle如何定位,应该还是有其他的方法。[/COLOR]
再探究一下,那些带(file #file_no block #block_id)的文件时如何来的?这很可能涉及到oracle的启动进程。在上面生成的oracle.txt中,可以发现这样的句子:
select rowcnt,blkcnt,empcnt,avgspc,chncnt,avgrln,nvl(degree,1), nvl(instances,1) from tab$ where obj# = :1
select blevel, leafcnt, distkey, lblkkey, dblkkey, clufac, nvl(degree,1), nvl(instances,1) from ind$ where bo# = :1 and obj# = :2
select charsetid, charsetform from col$ where obj# = :1 and col# = :2
create table bootstrap$ ( line# number not null, obj# number not null, sql_text varchar2(%d) not null) storage (initial 50K objno %d extents (file %d block %d))
BOOTSTRAP$
boot strap sql text
sql statement buffer
select line#, sql_text from bootstrap$ where obj# != :1
KQLBEBS: %2d %.65s
HIST_HEAD$
HISTGRM$
FIXED_OBJ$
TAB_STATS$
IND_STATS$
I_HH_OBJ#_COL#
I_HH_OBJ#_INTCOL#
I_OBJ#_INTCOL#
I_H_OBJ#_COL#
I_FIXED_OBJ$_OBJ#
I_TAB_STATS$_OBJ#
I_IND_STATS$_OBJ#
C_OBJ#_INTCOL#
OBJECT_USAGE
OBJAUTH$
WARNING: kqlblnb() has detected that %s does not exist.
kqlb.c
insert into bootstrap$ values (:1, :1, :2)
kqlbbotadd
kqlbbotadd:2
kqlbbotadd:3
select charsetid, charsetform from col$ where obj# = :1 and col# = :2
这样看来,更像是通过读出相关的信息来生成表的创建语句和填充数据。 基本可以推定在trace中生成的create table bootstrap$ 等sql是由oracle这个可执行程序来生成的。[/COLOR]
下面来测试一下是否可以删除它的数据呢?当我delete了数据后重新启动数据库,可以发现数据库启动不了:
create table bootstrap$ ( line# number not null, obj# number not null, sql_text varchar2(4000) not null) storage (initial 50K objno 56 extents (file 1 block 633))
END OF STMT
PARSE #2:c=10000,e=721,p=0,cr=0,cu=0,mis=1,r=0,dep=1,og=4,tim=1128463030949841
EXEC #2:c=0,e=210,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,tim=1128463030950164
=====================
PARSING IN CURSOR #2 len=55 dep=1 uid=0 oct=3 lid=0 tim=1128463030950823 hv=2111436465 ad='307479b8'
select line#, sql_text from bootstrap$ where obj# != :1
END OF STMT
PARSE #2:c=0,e=554,p=0,cr=0,cu=0,mis=1,r=0,dep=1,og=4,tim=1128463030950818
EXEC #2:c=0,e=917,p=0,cr=0,cu=0,mis=1,r=0,dep=1,og=4,tim=1128463030951901
FETCH #2:c=0,e=520,p=4,cr=5,cu=0,mis=0,r=0,dep=1,og=4,tim=1128463030952477
ORA-00704: bootstrap process failure
ORA-00702: bootstrap verison '' inconsistent with version '8.0.0.0.0'
EXEC #1:c=50000,e=2870560,p=661,cr=6,cu=0,mis=0,r=0,dep=0,og=1,tim=1128463032081269
ERROR #1:err=1092 tim=8458790
另外推定:不要轻易重建数据字典表,很可能会碰到大问题。如果是通过bootstrap$来reference其他表格的话,如果重建表格而更改了起始块,
使它与bootstrap$中的不相一致,这样就很可能会发生找不到表格的问题,使数据库启动失败。[/COLOR]
所以对于oracle如何找到"引导块",还是要考虑其他的方法。 |
|