加载oracle数据库数据字典,深入了解Oracle数据字典

——深入了解Oracle数据字典,提高自学习Oracle能力

摘要:

我们知道Oracle通过数据字典来管理和展现数据库信息,这些信息至关重要。正确理解这部分内容有助于加强我们的oracle学习能力。

本文对Oracle数据字典的关系进行探讨。

接下来我们介绍一下怎样通过数据库本身来学习研究数据库。

首先,Oracle的字典表和视图基本上可以分为三个层次。

1.1 X$表

这一部分表是Oracle数据库的运行基础,在数据库启动时由Oracle应用程序动态创建。

这部分表对数据库来说至关重要,所以Oracle不允许SYSDBA之外的用户直接访问,显示授权不被允许。

如果显示授权你会收到如下错误:

SQL> grant select on x$ksppi to eygle;

grant select on x$ksppi to eygle

*

ERROR at line 1:

ORA-02030: can only select from fixed tables/views

Oracle的解释是:

ORA-02030 can only select from fixed tables/views

Cause: An attempt is being made to perform an operation other than a retrieval from a fixed table/view.

Action: You may only select rows from fixed tables/views.

一句话,这些对象你只能查询。

1.2 GV$和V$视图

在创建了X$表之后,Oracle创建了GV$和V$视图。 从Oracle8开始,GV$视图开始被引入,其含义为Global V$。

除了一些特例以外,每个V$视图都有一个对应的GV$视图存在。

GV$视图的产生是为了满足OPS环境的需要,在OPS环境中,查询GV$视图返回所有实例信息,而每个V$视图是基于GV$视图,增加了INST_ID列的WHERE条件限制建立,只包含当前连接实例信息。

注意,每个V$视图都包含类似语句:

where inst_id = USERENV('Instance')

用于限制返回当前实例信息。

我们从GV$FIXED_TABLE和V$FIXED_TABLE开始,看一下GV$视图和V$视图的结构:

SQL> select view_definition from v$fixed_view_definition where view_name='V$FIXED_TABLE';

VIEW_DEFINITION

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

select NAME , OBJECT_ID , TYPE , TABLE_NUM from GV$FIXED_TABLE where inst_id = USERENV('Instance')

这里我们看到V$FIXED_TABLE基于GV$FIXED_TABLE创建。

SQL> select view_definition from v$fixed_view_definition where view_name='GV$FIXED_TABLE';

VIEW_DEFINITION

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

select inst_id,kqftanam, kqftaobj, 'TABLE', indx from x$kqfta

union all

select inst_id,kqfvinam, kqfviobj, 'VIEW', 65537 from x$kqfvi

union all

select inst_id,kqfdtnam, kqfdtobj, 'TABLE', 65537 from x$kqfdt

这样我们找到了GV$FIXED_TABLE视图的创建语句,该视图基于X$表创建。

我们知道,GV$视图和V$视图是在数据库创建过程中建立起来的,内置于数据库中,Oracle通过v$fixed_view_definition视图为我们展现这些定义。

1.3 GV_$,V_$视图和V$,GV$同义词

在GV$和V$之后,Oracle建立了GV_$和V_$视图,随后为这些视图建立了公用同义词。这些工作都是通过catalog.sql脚本实现的。

我们从catalog.sql脚本中摘录一段:

create or replace view v_$fixed_table as select * from v$fixed_table;

create or replace public synonym v$fixed_table for v_$fixed_table;

create or replace view gv_$fixed_table as select * from gv$fixed_table;

create or replace public synonym gv$fixed_table for gv_$fixed_table;

从以上脚本中,我们注意到,第一个视图V_$和GV_$视图基于V$和GV$视图首先被创建,然后基于V_$和GV_$视图的同义词被创建。

通过V_$视图,Oracle把V$视图和普通用户隔离,V_$视图的权限可以授予其他用户,而Oracle不允许任何对于V$视图的直接授权,我们看以下例子:

[oracle@jumper udump]$ sqlplus '/ as sysdba'

SQL*Plus: Release 9.2.0.4.0 - Production on Mon Jun 13 16:41:41 2005

Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.

Connected to:

Oracle9i Enterprise Edition Release 9.2.0.4.0 - Production

With the Partitioning option

JServer Release 9.2.0.4.0 - Production

SQL> grant select on v$sga to eygle;

grant select on v$sga to eygle

*

ERROR at line 1:

ORA-02030: can only select from fixed tables/views

SQL> grant select on v_$sga to eygle;

Grant succeeded.

对于内部X$表及V$视图的限制,我猜测是通过软件代码实现的,而并非通过数据库权限控制。

所以,实际上通常我们大部分用户访问的V$对象,并不是视图,而是指向V_$视图的同义词;而V_$视图是基于真正的V$视图(这个视图是基于X$表建立的)。

在进行数据访问时,Oracle访问VIEW优先,然后是同义词。我们通过以下实验来验证一下这个结论。

首先参考Oracle处理机制,创建X$EYGLE,V$EYGLE,V_$EYGLE和公用同义词V$EYGLE:

[oracle@jumper udump]$ sqlplus eygle/eygle

SQL*Plus: Release 9.2.0.4.0 - Production on Mon Jun 13 17:37:25 2005

Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.

Connected to:

Oracle9i Enterprise Edition Release 9.2.0.4.0 - Production

With the Partitioning option

JServer Release 9.2.0.4.0 - Production

SQL> create table x$eygle as select username from dba_users;

Table created.

SQL> create view v$eygle as select * from x$eygle;

View created.

SQL> create view v_$eygle as select * from v$eygle;

View created.

SQL> create public synonym v$eygle for v_$eygle;

Synonym created.

然后我们在sys用户下创建V$EYGLE视图:

SQL> connect / as sysdba

Connected.

SQL> create view v$eygle as select username,user_id from dba_users;

View created.

此时查询,我们得到的SYS的V$EYGLE信息:

SQL> desc v$eygle;

Name Null? Type

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

USERNAME NOT NULL VARCHAR2(30)

USER_ID NOT NULL NUMBER

当我们删除这个视图以后,再次访问时,Oracle选择访问了V$EYGLE同义词:

SQL> drop view v$eygle ;

View dropped.

SQL> desc v$eygle

Name Null? Type

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

USERNAME NOT NULL VARCHAR2(30)

SQL>

v$fixed_view_definition视图是我们研究Oracle对象关系的一个入口,仔细理解Oracle的数据字典机制,有助于深入了解和学习Oracle数据库知识。

1.4 再进一步

1.4.1 数据库的初始化

首先我们考察bootstrap$表,该表中记录了数据库启动的基本及驱动信息。

SQL> col line# for 99

SQL> col obj# for 99

SQL> select * from bootstrap$ order by line#;

LI OB SQL_TEXT

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

-1 -1 8.0.0.0.0

0 0 CREATE ROLLBACK SEGMENT SYSTEM STORAGE ( INITIAL 112K NEXT 1024K MINEXTENTS 1 M

2 2 CREATE CLUSTER C_OBJ#("OBJ#" NUMBER) PCTFREE 5 PCTUSED 40 INITRANS 2 MAXTRANS 25

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

4 4 CREATE TABLE TAB$("OBJ#" NUMBER NOT NULL,"DATAOBJ#" NUMBER,"TS#" NUMBER NOT NULL

5 5 CREATE TABLE CLU$("OBJ#" NUMBER NOT NULL,"DATAOBJ#" NUMBER,"TS#" NUMBER NOT NULL

6 6 CREATE CLUSTER C_TS#("TS#" NUMBER) PCTFREE 10 PCTUSED 40 INITRANS 2 MAXTRANS 255

7 7 CREATE INDEX I_TS# ON CLUSTER C_TS# PCTFREE 10 INITRANS 2 MAXTRANS 255 STORAGE (

8 8 CREATE CLUSTER C_FILE#_BLOCK#("TS#" NUMBER,"SEGFILE#" NUMBER,"SEGBLOCK#" NUMBER)

9 9 CREATE INDEX I_FILE#_BLOCK# ON CLUSTER C_FILE#_BLOCK# PCTFREE 10 INITRANS 2 MAXT

10 10 CREATE CLUSTER C_USER#("USER#" NUMBER) PCTFREE 10 PCTUSED 40 INITRANS 2 MAXTRANS

11 11 CREATE INDEX I_USER# ON CLUSTER C_USER# PCTFREE 10 INITRANS 2 MAXTRANS 255 STORA

12 12 CREATE TABLE FET$("TS#" NUMBER NOT NULL,"FILE#" NUMBER NOT NULL,"BLOCK#" NUMBER

13 13 CREATE TABLE UET$("SEGFILE#" NUMBER NOT NULL,"SEGBLOCK#" NUMBER NOT NULL,"EXT#"

14 14 CREATE TABLE SEG$("FILE#" NUMBER NOT NULL,"BLOCK#" NUMBER NOT NULL,"TYPE#" NUMBE

15 15 CREATE TABLE UNDO$("US#" NUMBER NOT NULL,"NAME" VARCHAR2(30) NOT NULL,"USER#" NU

16 16 CREATE TABLE TS$("TS#" NUMBER NOT NULL,"NAME" VARCHAR2(30) NOT NULL,"OWNER#" NUM

17 17 CREATE TABLE FILE$("FILE#" NUMBER NOT NULL,"STATUS$" NUMBER NOT NULL,"BLOCKS" NU

18 18 CREATE TABLE OBJ$("OBJ#" NUMBER NOT NULL,"DATAOBJ#" NUMBER,"OWNER#" NUMBER NOT N

19 19 CREATE TABLE IND$("OBJ#" NUMBER NOT NULL,"DATAOBJ#" NUMBER,"TS#" NUMBER NOT NULL

....

这部分信息,在数据库启动时最先被加载,跟踪数据库的启动过程,我们发现数据库启动的第一个动作就是:

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

这部分代码是写在Oracle应用程序中的,在内存中创建了bootstrap$以后,Oracle就可以从file 1,block 377上读取其他信息,创建重要的数据库对象。从而根据这一部分信息启动数据库,这就实现了数据库的引导,类似于操作系统的初始化。

这部分你可以参考biti_rainy在Itpub上的文章(http://www.itpub.net/199099.html)。

Oracle的X$表信息可以从v$fixed_table中查到:

SQL> select count(*) from v$fixed_table where name like 'X$%';

COUNT(*)

----------

394

对于Oracle9iR2,共有394个X$对象被记录。

1.4.2 GV$和V$视图

X$表建立以后,基于X$表的GV$和V$视图得以创建。

这部分视图我们也可以通过查询V$FIXED_TABLE得到。

SQL> select count(*) from v$fixed_table where name like 'GV$%';

COUNT(*)

----------

259

这一部分共259个对象。

SQL> select count(*) from v$fixed_table where name like 'V$%';

COUNT(*)

----------

259

同样是259个对象。

v$fixed_table共记录了:

394 + 259 + 259 共 912 个对象。

SQL> select count(*) from v$fixed_table;

COUNT(*)

----------

912

以上是Oracle9iR2单机环境中的数据:

SQL> select * from v$version;

BANNER

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

Oracle9i Enterprise Edition Release 9.2.0.4.0 - Production

PL/SQL Release 9.2.0.4.0 - Production

CORE 9.2.0.3.0 Production

TNS for Linux: Version 9.2.0.4.0 - Production

NLSRTL Version 9.2.0.4.0 - Production

1.5 最后的验证

最后然我们通过V$PARAMETER视图来追踪一下数据库的架构:

1.5.1 V$PARAMETER的结构

SQL> select view_definition from v$fixed_view_definition a where a.VIEW_NAME='V$PARAMETER';

VIEW_DEFINITION

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

select NUM , NAME , TYPE , VALUE , ISDEFAULT , ISSES_MODIFIABLE , ISSYS_MODIFIA

BLE , ISMODIFIED , ISADJUSTED , DESCRIPTION, UPDATE_COMMENT from GV$PARAMETER wh

ere inst_id = USERENV('Instance')

我们看到V$PARAMETER是由GV$PARAMETER创建的,GV$PARAMETER则是由X$创建的。

SQL> select view_definition from v$fixed_view_definition a where a.VIEW_NAME='GV$PARAMETER';

VIEW_DEFINITION

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

select x.inst_id,x.indx+1,ksppinm,ksppity,ksppstvl,ksppstdf, decode(bitand(kspp

iflg/256,1),1,'TRUE','FALSE'), decode(bitand(ksppiflg/65536,3),1,'IMMEDIATE',2,

'DEFERRED', 3,'IMMEDIATE','FALSE'), decode(bit

and(ksppstvf,7),1,'MODIFIED',4,'SYSTEM_MOD','FALSE'), decode(bitand(ksppstvf,2)

,2,'TRUE','FALSE'), ksppdesc, ksppstcmnt from x$ksppi x, x$ksppcv y where (x.i

ndx = y.indx) and ((translate(ksppinm,'_','#') not like '#%') or (ksppstdf = 'F

ALSE'))

说明:在这里我们看到GV$PARAMETER来源于x$ksppi,x$ksppcv两个X$表。 x$ksppi,x$ksppcv 基本上包含所有数据库参数,v$parameter展现的是不包含"_"开头的参数。以"_"开头的参数我们通常称为隐含参数,一般不建议修改,但很多因为功能强大经常使用而广为人知。

1.5.2 视图还是同义词

在非SYS用户下查询,很多朋友曾经提出过疑问,那就是,当我访问V$PARAMETER对象时,访问的是视图还是同义词?

如果你还记得我们前面讲过的内容,那么你会知道,毫无疑问,这里访问的是同义词,因为除了SYS用户以外,其他用户不能查询V$视图,V$视图也不能被授权给其他用户。

那么这个问题实际上是不成立的。

SQL> connect / as sysdba

Connected.

SQL> grant select on v$parameter to eygle;

grant select on v$parameter to eygle

*

ERROR at line 1:

ORA-02030: can only select from fixed tables/views

SQL> connect eygle/eygle

Connected.

SQL> desc sys.v$parameter

ERROR:

ORA-04043: object sys.v$parameter does not exist

SQL> desc v$parameter

Name Null? Type

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

NUM NUMBER

NAME VARCHAR2(64)

TYPE NUMBER

VALUE VARCHAR2(512)

ISDEFAULT VARCHAR2(9)

ISSES_MODIFIABLE VARCHAR2(5)

ISSYS_MODIFIABLE VARCHAR2(9)

ISMODIFIED VARCHAR2(10)

ISADJUSTED VARCHAR2(5)

DESCRIPTION VARCHAR2(64)

UPDATE_COMMENT VARCHAR2(255)

1.5.3 Oracle如何通过同义词定位对象

如果愿意的话,我们可以进一步来进行追溯,使用10046事件,我们可以看到更多的东西。

通过10046事件跟踪查询:

[oracle@jumper udump]$ sqlplus eygle/eygle

SQL*Plus: Release 9.2.0.4.0 - Production on Mon Jun 13 18:29:22 2005

Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.

Connected to:

Oracle9i Enterprise Edition Release 9.2.0.4.0 - Production

With the Partitioning option

JServer Release 9.2.0.4.0 - Production

SQL> alter session set events '10046 trace name context forever,level 12';

Session altered.

SQL> select count(*) from v$parameter;

COUNT(*)

----------

262

SQL> exit

Disconnected from Oracle9i Enterprise Edition Release 9.2.0.4.0 - Production

With the Partitioning option

JServer Release 9.2.0.4.0 - Production

10046事件的使用请参考:

Ok,在这里我们不要使用tkprof格式化,因为tkprof可能会隐去重要信息(本文仅摘取几段重要跟踪信息,你完全可以通过实验获得相同的输出):

第一段重要代码是:

PARSING IN CURSOR #2 len=198 dep=1 uid=0 oct=3 lid=0 tim=1092440257023120 hv=2703824309 ad='567681f0'

select obj#,type#,ctime,mtime,stime,status,dataobj#,flags,oid$, spare1, spare2 from obj$ where owner#=:1 and name=:2 and namespace=:3 and remoteowner is null and linkname is null and subname is null

END OF STMT

PARSE #2:c=0,e=1601,p=0,cr=0,cu=0,mis=1,r=0,dep=1,og=0,tim=1092440257023088

BINDS #2:

bind 0: dty=2 mxl=22(22) mal=00 scl=00 pre=00 oacflg=08 oacfl2=1 size=24 offset=0

bfp=b701cf24 bln=22 avl=02 flg=05

value=25

bind 1: dty=1 mxl=32(11) mal=00 scl=00 pre=00 oacflg=18 oacfl2=1 size=32 offset=0

bfp=b701c7b4 bln=32 avl=11 flg=05

value="V$PARAMETER"

bind 2: dty=2 mxl=22(22) mal=00 scl=00 pre=00 oacflg=08 oacfl2=1 size=24 offset=0

bfp=b701c790 bln=24 avl=02 flg=05

value=1

Oracle根据三个传入参数owner#=25,name=V$PARAMETER,namespace=1,来判断对象类型,按照表、视图优先规则来定位判断,对于本例这个查询是不会有结果的。

接下来Oracle继续判断,那么此时需要验证同一词了:

PARSING IN CURSOR #4 len=46 dep=1 uid=0 oct=3 lid=0 tim=1092440257028409 hv=3378994511 ad='576eb040'

select node,owner,name from syn$ where obj#=:1

END OF STMT

PARSE #4:c=0,e=1278,p=0,cr=0,cu=0,mis=1,r=0,dep=1,og=0,tim=1092440257028379

BINDS #4:

bind 0: dty=2 mxl=22(22) mal=00 scl=00 pre=00 oacflg=08 oacfl2=1 size=24 offset=0

bfp=b701b3cc bln=22 avl=03 flg=05

value=841

传入绑定变量值是841,我们看看841是什么:

SQL> select object_name,object_id,object_type from dba_objects where object_id=841;

OBJECT_NAME OBJECT_ID OBJECT_TYPE

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

V$PARAMETER 841 SYNONYM

841正是这个同义词,我们再继续看这个递归SQL的作用:

SQL> select node,owner,name from syn$ where obj#=841;

NODE OWNER NAME

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

SYS V_$PARAMETER

原来这个SQL获得的是同义词的底层对象,这里得到了V_$PARAMETER。

我们继续向下看:

PARSING IN CURSOR #8 len=37 dep=1 uid=0 oct=3 lid=0 tim=1092440257074273 hv=3468666020 ad='576db210'

select text from view$ where rowid=:1

END OF STMT

PARSE #8:c=0,e=1214,p=0,cr=0,cu=0,mis=1,r=0,dep=1,og=0,tim=1092440257074242

BINDS #8:

bind 0: dty=11 mxl=16(16) mal=00 scl=00 pre=00 oacflg=18 oacfl2=1 size=16 offset=0

bfp=b7018770 bln=16 avl=16 flg=05

value=000001CD.0013.0001

EXEC #8:c=0,e=972,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,tim=1092440257075602

注意这里,Oracle执行查询访问view$视图,获得视图定义文本,我们看一下这里访问的是什么对象,绑定变量传入的rowid值为000001CD.0013.0001,注意这是个受限rowid,查询时需要转换一下处理:

SQL> select obj# from view$ where dbms_rowid.rowid_to_restricted(rowid,0) = '000001CD.0013.0001';

OBJ#

----------

840

SQL> select object_name,object_type from dba_objects where object_id=840;

OBJECT_NAME OBJECT_TYPE

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

V_$PARAMETER VIEW

这里Oracle访问的正是V_$PARAMETER视图的定义方式。执行查询可以得到:

select text from view$ where obj#=840;

TEXT

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

select "NUM","NAME","TYPE","VALUE","ISDEFAULT","ISSES_MODIFIABLE","ISSYS_MODIFIABLE","ISMODIFIED","ISADJUSTED","DESCRIPTION","UPDATE_COMMENT" from v$parameter

至此就完成了查询中的回溯及定位,当然,实际过程中Oracle后台的递归操作比这还要复杂的多,感兴趣的朋友可以按照文中的方法测试研究一下,文中不再赘述。

参考文献:

使用SQL_TRACE进行数据库诊断

Oracle数据库创建脚本 sql.bsq文件

关于数据库open的深入探究

http://www.itpub.net/199099.html

阅读(822) | 评论(0) | 转发(0) |

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值