ITPub博客

首页 > Linux操作系统 > Linux操作系统 > 从视图看Oracle对象依赖机制

从视图看Oracle对象依赖机制

原创 Linux操作系统 作者:realkid4 时间:2012-03-18 22:37:09 1 删除 编辑

 

Oracle中,很多对象之间是存在着依赖关系的。比如:视图view与其包括的数据表、存储过程与其内部使用的方法等。Oracle对于对象的依赖关系,是有专门的管理机制流程的。在本篇中,我们一起来探讨这种依赖关系。

 

本篇实验我们选择“view+table”的简单依赖模式进行研究。

 

1、 实验环境

 

我们选择Oracle 10gR2进行试验。

 

 

SQL> select * from v$version;

 

BANNER

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

Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod

PL/SQL Release 10.2.0.1.0 - Production

CORE    10.2.0.1.0    Production

TNS for 32-bit Windows: Version 10.2.0.1.0 - Production

NLSRTL Version 10.2.0.1.0 Production

 

 

创建实验数据表,以及依赖数据表的视图。

 

 

SQL> create table t as select * from dba_objects where wner='SCOTT';

Table created

 

SQL> create view v_t as select * from t;

View created

 

SQL> select text_length, text from dba_views where view_name='V_T' and wner='SCOTT';

 

TEXT_LENGTH TEXT

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

        180 select "OWNER","OBJECT_NAME","SUBOBJECT_NAME","OBJECT_ID","DATA_OBJECT_ID","OBJE

 

 

2、依赖关系判断规则

 

数据表T和视图V_T之间存在对象依赖关系。如果数据表T被删除,那么视图V_T就不能是存在的。

 

首先,我们从dba_objects视图中,可以看到v_t是valid状态。

 

 

SQL> col object_name for a10;

SQL> select object_name, object_type, status from dba_objects where wner='SCOTT' and object_name='V_T';

 

OBJECT_NAM OBJECT_TYPE         STATUS

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

V_T        VIEW                VALID

 

 

如果我们删除数据表T,那么视图v_t的状态是如何变化呢?

 

 

SQL> drop table t;

Table dropped

 

SQL> select object_name, object_type, status from dba_objects where wner='SCOTT' and object_name='V_T';

 

OBJECT_NAM OBJECT_TYPE         STATUS

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

V_T        VIEW                INVALID

 

 

注意:当我们删除一个底层被依赖对象的时候,会发现依赖对象(如视图V_T)就联动的状态变化为失效。

 

如果我们此时使用v_t,系统报错。

 

 

SQL> select count(*) from v_t;

select count(*) from v_t

 

ORA-04063: view "SCOTT.V_T" 有错误

 

 

这个时候,我们恢复底层的对象T,即使对象已经不是原来的T(object_id变化)。

 

 

SQL> create table t as select * from dba_objects where wner='SCOTT';

Table created

 

SQL> select object_name, object_type, status from dba_objects where wner='SCOTT' and object_name='V_T';

 

OBJECT_NAM OBJECT_TYPE         STATUS

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

V_T        VIEW                INVALID

 

 

我们从底层恢复了数据表T,发现视图v_t并没有联动的变化为valid,而是保持了invalid状态。那么,这个时候,如果我们调用v_t,是否报错呢?

 

 

SQL> select count(*) from v_t;

 

  COUNT(*)

----------

        49

 

SQL> select object_name, object_type, status from dba_objects where wner='SCOTT' and object_name='V_T';

 

OBJECT_NAM OBJECT_TYPE         STATUS

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

V_T        VIEW                VALID

 

 

当我们使用视图的时候,视图可以正常工作。而且当使用之后检查dba_objects视图,状态已经修复为valid。

 

通过上面的实验,我们可以猜测:当我们修改、删除一个对象的时候,依赖该对象的对象状态会以递归的方式变化(依赖链超过两层时,效果相同)。当我们恢复这个对象状态时候,连带的被依赖对象是不会连带的恢复状态的。

 

进一步说,如果对象状态是invalid,Oracle在使用的时候,会首先尝试的编译一下对象,看看是否状态真的是invalid。如果确定是invalid,就报错。如果不是invalid状态,就重置状态,并且返回结果。

 

3、 深层分析对象删除操作

 

那么,我们假定猜测,是建立在Oracle内部有保存对象以来关系的数据字典。这个视图字典就是dba_dependencies,我们可以从这个视图中找到所有对象的依赖关系。这个依赖关系是对象在创建的时候就已经确立的。

 

 

SQL> select owner, name ,type, referenced_owner, referenced_name, referenced_type from dba_dependencies where wner='SCOTT' and name='V_T';

 

OWNER      NAME       TYPE       REFERENCED REFERENCED REFERENCED

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

SCOTT      V_T        VIEW       SCOTT      T          TABLE

 

 

那么,我们猜想,在drop一个数据库对象的时候,连带内部会去检查依赖关系,并且更新obj$基础表。

 

为了验证我们的想法,使用10046事件跟踪动作。

 

 

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

会话已更改。

 

SQL> drop table t;

表已删除。

 

SQL> alter session set events '10046 trace name context off';

会话已更改。

 

SQL> select f_get_trace_name from dual;

 

F_GET_TRACE_NAME

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

C:\TOOL\ORACLE\ORACLE\PRODUCT\10.2.0\ADMIN\OTS\UDUMP\ots_ora_5764.trc

 

 

我们首先使用tkprof分析跟踪文件raw格式文件。

 

 

D:\>tkprof ots_ora_5764.trc testres.txt

 

TKPROF: Release 10.2.0.1.0 - Production on 星期三 3月 14 15:39:08 2012

 

Copyright (c) 1982, 2005, Oracle.  All rights reserved.

 

 

 

在生成的格式化文件中,我们看到两个递归SQL值得注意。

 

 

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

 

select o.owner#, u.name,        o.name,            o.namespace,    o.obj#,  

  d.d_timestamp, nvl(d.property,0), o.type#, o.subname, d.d_attrs 

from

 dependency$ d, obj$ o, user$ u  where d.p_obj#=:1  and   (d.p_timestamp=:2

  or d.property=2)  and   d.d_obj#=o.obj#  and   o.owner#=u.user#  order by

  o.obj#

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

 

update obj$ set obj#=:6,type#=:7,ctime=:8,mtime=:9,stime=:10,status=:11,

  dataobj#=:13,flags=:14,oid$=:15,spare1=:16, spare2=:17

where

 owner#=:1 and name=:2 and namespace=:3 and(remoteowner=:4 or remoteowner is

  null and :4 is null)and(linkname=:5 or linkname is null and :5 is null)

  and(subname=:12 or subname is null and :12 is null)

 

 

 

两句SQL中,一个是对dependency$原数据表进行查询,另一个是更新obj$数据表。Dependency$是视图dba_dependencies的底层依赖视图,而obj$又是dba_objects的基础数据表。

 

我们猜测,正是这两个SQL来实现的dba_objects中状态变量的变化。首先从依赖关系中找到对应对象的依赖对象信息,之后进行更新obj$操作。

 

要最后确定这一点,还要从raw中进行分析,找到对应bind value的取值。

 

 

PARSING IN CURSOR #7 len=331 dep=2 uid=0 ct=6 lid=0 tim=1751712040001 hv=2997034431 ad='288ce494'

update obj$ set obj#=:6,type#=:7,ctime=:8,mtime=:9,stime=:10,status=:11,dataobj#=:13,flags=:14,oid$=:15,spare1=:16, spare2=:17 where owner#=:1 and name=:2 and namespace=:3 and(remoteowner=:4 or remoteowner is null and :4 is null)and(linkname=:5 or linkname is null and :5 is null)and(subname=:12 or subname is null and :12 is null)

END OF STMT

PARSE #7:c=0,e=10730,p=0,cr=0,cu=0,mis=1,r=0,dep=2,og=4,tim=1751712039992

BINDS #7:

 

 

 

其中绑定变量

 

 

Bind#0

  oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00

  oacflg=08 fl2=0001 frm=00 csi=00 siz=24 ff=0

  kxsbbbfp=0868872c  bln=24  avl=04  flg=05

  value=115068

 

 

Bind#12

  oacdty=01 mxl=32(03) mxlc=00 mal=00 scl=00 pre=00

  oacflg=18 fl2=0001 frm=01 csi=852 siz=32 ff=0

  kxsbbbfp=1fe33c4e  bln=32  avl=03  flg=09

  value="V_T"

 

 

显然是要求修改v_t信息,而修改的最终取值status为:

 

 

Bind#5

  oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00

  oacflg=08 fl2=0001 frm=00 csi=00 siz=24 ff=0

  kxsbbbfp=086886e4  bln=24  avl=02  flg=05

  value=5

 

 

object_id为115068恰恰为视图v_t的统一对象编号。目前他的状态被修改为5,对应的含义取值为invalid。

 

 

 

SQL> select owner, object_name, object_id from dba_objects where object_id=115068;

 

OWNER      OBJECT_NAM  OBJECT_ID

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

SCOTT      V_T            115068

 

 

SQL> select namespace, status from obj$ where obj#=115068;

 

 NAMESPACE     STATUS

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

1        5

 

 

另一个select SQL语句中,我们可以看到端倪。

 

 

PARSING IN CURSOR #1 len=302 dep=2 uid=0 ct=3 lid=0 tim=1751712024277 hv=444865451 ad='288cdfd4'

select o.owner#, u.name,        o.name,            o.namespace,    o.obj#,   d.d_timestamp, nvl(d.property,0), o.type#, o.subname, d.d_attrs  from dependency$ d, obj$ o, user$ u  where d.p_obj#=:1  and   (d.p_timestamp=:2 or d.property=2)  and   d.d_obj#=o.obj#  and   o.owner#=u.user#  order by o.obj#

END OF STMT

 

Bind#0

  oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00

  oacflg=00 fl2=0001 frm=00 csi=00 siz=32 ff=0

  kxsbbbfp=0868b3a8  bln=22  avl=04  flg=05

  value=115069

 

 

 

这个115069是何许人也呢?

 

 

SQL> select owner, object_name, object_id from dba_objects where object_id=115069;

 

OWNER      OBJECT_NAM  OBJECT_ID

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

SCOTT      BIN$s/c/tF     115069

           QdQG28enjy

           QCtSdQ==$0

 

 

就是那个已经被删除的数据表t,这里我们还可以查到他是因为Oracle的flashback drop机制存在。

 

4、结论

 

Oracle数据库对象之间是存在着有组织的依赖关系的。这种关系维护是通过内部的数据字典来进行。当我们让一个底层对象失效,依赖它的所有对象都会设置为invalid。而且这个连带变化是单向多层次进行的,通常不会出现底层对象失效,而上层对象保持为valid的场景。

 

但是,对象状态恢复却不是这样。一个对象变为valid之后,依赖它的对象状态不会连带的更新为valid。只是当对象被使用的时候,Oracle内部会对invalid对象有一个compile的动作。

 

Oracle这样做的原因,个人臆测是这样的:对象的失效过程,需要将对象依赖链上级的所有对象直接设置为invalid就可以了。这个操作递归过程相当简单,融合在delete操作或者其他中不会有很大的影响。

 

但是对象valid过程却绝不简单。一个底层对象恢复了valid,上层是不一定恢复的。因为上层对象可能依赖多个invalid对象,要确定所有的对象都是valid的。这样就由一个遍历链变成了深度遍历树的过程。从性能上,潜在压力是巨大的。

 

所以,之所以有这样的机制,恐怕还是oracle基于性能的一种这种考量。

 

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/17203031/viewspace-718906/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
求道~

注册时间:2010-11-30

  • 博文量
    545
  • 访问量
    7645730