关于non-existent objects与negative dependency
上一篇:通过standby instance实现远程归档 下一篇:升级到wordpress2.3

关于non-existent objects与negative dependency

logzgh的blog上看到《在obj$基表中大量的non-existent类型对象是咋回事?》。这里简单解释下non-existent objectnegative dependency

对于Non-existent object,有两种来源,一种是drop或者rename object留下的,一种则是因为negative dendency机制。在我的试验中,这两种情况实际上都和synonym有关。

第一种情况,对于table,view等对象的drop/rename,我没有试验到non-existent的存在,但是在删除synonym时,可以看到Obj$实际上没有删除该synonym的记录,只是将其type#从5修改成10,也就是变成了non-existent

NING@ ning>create table test_synonym(i int);

表已创建。

NING@ ning>grant select on test_synonym to test;

授权成功。

TEST@ ning>create synonym test_synonym for ning.test_synonym;

同义词已创建。

SYS@ ning>select obj#,name,type# from obj$ where name='TEST_SYNONYM';

      OBJ# NAME                                TYPE#
---------- ------------------------------ ----------
     44651 TEST_SYNONYM                            2
     44652 TEST_SYNONYM                            5

其中type#=2的是table,type#=5的是synonym

TEST@ ning>drop synonym test_synonym;

同义词已删除。

SYS@ ning>select obj#,name,type# from obj$ where name='TEST_SYNONYM';

      OBJ# NAME                                TYPE#
---------- ------------------------------ ----------
     44651 TEST_SYNONYM                            2
     44652 TEST_SYNONYM                           10

这种情况,在数据库没有重启之前,再次创建该synonym,可以重用obj#,也就是讲type#再修改回来,这样就不会因为不停的删除重建对象导致obj$出现太多的垃圾。重启的时候,这些non-existent应该是由smon清理掉的。

TEST@ ning>create synonym test_synonym for ning.test_synonym;

同义词已创建。

SYS@ ning>select obj#,name,type# from obj$ where name='TEST_SYNONYM';

      OBJ# NAME                                TYPE#
---------- ------------------------------ ----------
     44651 TEST_SYNONYM                            2
     44652 TEST_SYNONYM                            5           
    
SYS@ ning>shutdown immediate;
数据库已经关闭。
已经卸载数据库。
ORACLE 例程已经关闭。
SYS@ ning>startup
ORACLE 例程已经启动。

Total System Global Area  130023424 bytes
Fixed Size                  1247660 bytes
Variable Size              79693396 bytes
Database Buffers           41943040 bytes
Redo Buffers                7139328 bytes
数据库装载完毕。
数据库已经打开。
SYS@ ning>select obj#,name,type# from obj$ where name='TEST_SYNONYM';

      OBJ# NAME                                TYPE#
---------- ------------------------------ ----------
     44651 TEST_SYNONYM                            2

至于第二种情况,则需要解释下什么是negative dependency。

对于一个查询中的对象,oracle是按照以下顺序来解析的:首先是current schema下找相应的对象如table,view或者private synonym,如果还没有就找public synonym,再没有就报ORA-00942了。

而对于依赖其他对象的对象,在被依赖对象出现变更后,可能会失效。这就需要有一种机制来保证oracle能对依赖关系进行跟踪。如果依赖的对象是current schem下的表,视图或者private synonym,则没有什么问题。如果是public synonym,则需要考虑的不仅是public synonym的变更会造成依赖其的对象失效,当依赖其的对象的schema下出现和public synonym相同名称的对象时,oracle应该是优先使用schema的对象,所以也需要使这些对象失效,以便重新解析到表或者视图上,private synonym没有这种问题,因为不允许在schema下出现同名的private synonym和table/view。这种情况下,oracle会在schema下创建一个non-existent对象,然后在该对象上创建一个依赖,如果以后schema下创建了同名的表或者视图,则non-existent对象被修改成实际创建的对象,使得依赖其的对象失效。Non-existent对象上的依赖就是negative denpendency。

上面讲的有些拗口,我自己都看得有点糊涂了,还是举个例子来看,注意不同语句是在不同用户下执行的:

NING@ ning>create table test_negative(i int);

表已创建。

NING@ ning>grant select on test_negative to test;

授权成功。

TEST@ ning>create public synonym test_negative for ning.test_negative;

同义词已创建。

TEST@ ning>create view v_test_negative
  2  as
  3  select * from test_negative;

视图已创建。

此时,由于test用户下没有叫test_negative的表或者视图,会通过public synonym来解析该对象,则会产生一个non-existent对象和一个negative dependency

SYS@ ning>select obj#,owner#,name,type# from obj$ where name='TEST_NEGATIVE';

      OBJ#     OWNER# NAME                                TYPE#
---------- ---------- ------------------------------ ----------
     44662          1 TEST_NEGATIVE                           5
     44661         42 TEST_NEGATIVE                           2
     44663         43 TEST_NEGATIVE                          10
    
SYS@ ning>select obj#,name,type# from obj$ where name='V_TEST_NEGATIVE';

      OBJ# NAME                                TYPE#
---------- ------------------------------ ----------
     44664 V_TEST_NEGATIVE                         4
    
SYS@ ning>select d_obj#,p_obj# from dependency$
  2  where d_obj#=44664;

    D_OBJ#     P_OBJ#   
---------- ----------
     44664      44663   
     44664      44662

可以看到,v_test_dependency出现了两个依赖,一个是对owner#为42的ning.test_negative表的依赖,一个则是对OWNER#为43的non-existent的test.test_negative的依赖。

此时,如果在test下创建一个test_negative表,则会使用原来的non-existent的obj#,也就是实际上不会再在obj$中插入记录,只是将原来的non-existent记录的type#从10修改为2,由于obj$记录变更,导致依赖失效,下次再访问该视图时,会重新编译解析到test.test_negative表上。

TEST@ ning>create table test_negative(i int);

表已创建。

SYS@ ning>select obj#,owner#,name,type# from obj$ where name='TEST_NEGATIVE';

      OBJ#     OWNER# NAME                                TYPE#
---------- ---------- ------------------------------ ----------
     44662          1 TEST_NEGATIVE                           5
     44661         42 TEST_NEGATIVE                           2
     44663         43 TEST_NEGATIVE                           2

NING@ ning>insert into test_negative values(10);

已创建 1 行。

NING@ ning>commit;

提交完成。

TEST@ ning>select * from v_test_negative;

未选定行

参考:
http://www.jlcomp.demon.co.uk/faq/non_exist.html
http://www.ixora.com.au/q+a/library.htm

本文网址:http://www.ningoo.net/html/2007/non_existent_objects_and_negative_dependency.html

订阅到Google | 收藏到Del.icio.us | 推荐到鲜果

相关文章 随机文章

本文Tags:

没有评论


(Required)
(Required, will not be published)