Oracle 概念(Oracle 10.2) 第六章 模式对象的依赖

Oracle 概念(Oracle 10.2)

6、模式对象的依赖

某些对象的定义引用了其他对象,比如视图和过程引用了表。因此,对象依赖于他们定义使用的对象。这一章描述了模式对象的依赖,以及Oracle如何自动跟踪和管理这种依赖。

这一章包含下列主题:

依赖发起介绍

模式对象依赖解决

对象名称解决

共享SQL依赖管理

本地和远程依赖管理

依赖发起介绍

某些类型的模式对象在定义中引用了其他的对象。例如,一个视图定义为一个引用了表或者其他视图的查询。一个过程体包含的SQL可以引用数据库的其他对象。一个在定义中引用其他对象的对象叫做依赖对象,而被引用的对象叫做引用对象。图6-1 显示了依赖对象和引用对象的区别:

图6-1 可能的依赖和引用模式对象的类型

如果你修改引用对象的定义,根据修改的类型,依赖对象可能也可能不继续起作用。例如,如果你删除了一个表,依赖删除表的任何视图都不可用。

Oracle自动记录对象之间的依赖,这样可以降低数据库管理员和用户管理依赖工作的复杂性。例如,如果你修改了一个表,但有几个存储过程依赖它,Oracle在过程下次被引用时(运行或者重新编译)自动重新编译依赖过程。

为管理模式对象之间的依赖性,数据库中的所有对象都有一个状态:

有效(Valid)模式对象是已经编译的对象,可以在引用时立刻使用

无效(Invalid)模式对象必须在使用之前编译:

² 对于过程、函数和包来说,这意味着编译模式对象

² 对视图来说,这意味着视图必须使用当前数据字典中的定义重新解析

只有依赖对象可以是无效状态,表、序列和同义词总是有效的。

如果视图、过程、函数或包是无效状态,Oracle可能已经试图编译它们,但是发生了错误。例如,当编译一个视图,其中的基表可能不存在或者没有对于基表足够的权限。当编译一个包,可能遇到一个PL/SQL或者SQL语法错误,或者引用对象没有足够的权限。模式对象遇到这种问题仍然是无效的。

Oracle自动跟踪数据库中定义的改变并在数据字典中记录相关对象的合适的状态。

状态记录是一个递归过程。引用对象状态的任何改变不仅改变直接依赖对象的状态,还影响间接依赖对象的状态。

例如,考虑一个直接引用一个视图的存储过程。实际上,存储过程间接的引用视图的基表。因而,如果你修改了基表的结构,视图就变成无效的了,然后会造成存储过程的无效。图6-2 显示了间接依赖:

图 6-2 间接依赖

模式对象依赖解决

当一个模式对象在SQL语句中直接或间接引用一个对象,Oracle根据需要会检查SQL语句中显示指定的对象或其他引用对象的状态。Oracle采取的行动依赖于在SQL语句中直接或间接指定的对象状态:

如果每个引用对象都是有效的,那么Oracle会立刻运行SQL语句,不用任何额外的工作。

如果引用的视图或者PL/SQL程序单位(过程、函数或包)无效,然后Oracle自动尝试编译对象:

² 如果一个无效对象能够成功编译,然后Oracle就会编译它们,然后执行SQL语句

² 如果一个无效对象不能成功编译,那么它还是无效的。Oracle返回一个错误并回滚失败的SQL语句。事务的剩余部分不做改变,可以被用户提交或者回滚。

注意:无效对象被检测为无效之后,只有在没有被替换的情况下,Oracle才会试图动态的重新编译无效对象。这个优化减少了不需要的重新编译。

视图和PL/SQL程序单位的编辑

视图或者PL/SQL程序单位只有在满足下列条件下才会编译,并生效:

视图或程序单位的定义必须是正确的。所有的SQL和PL/SQL语句必须是正确组织的。

所有的引用对象必须存在和有希望的结构。例如,如果视图的查询定义包含一个列,这个列必须在基表中存在。

视图或程序单位的拥有者必须拥有引用对象的必要的权限。例如,如果一个过程的SQL语句要插入一行到一个表中,过程的拥有者必须对引用表有INSERT权限。

视图和基表

视图依赖于查询定义中的基表或引用的视图。如果查询定义没有明确引用的列,例如,SELECT * FROM table,然后查询定义被展开,保存到数据字典的定义包含当时引用表的所有的列。

如果视图的基表或引用视图被修改、重命名或者删除,然后视图就是无效的,但是它的定义和包括引用这个无效视图的权限、同义词、其他对象以及其他视图仍保存在数据字典中。

注意:无论什么时候你创建了表、索引、视图,然后删除表,依赖表的所有对象都是无效的,包括视图、包、包体、函数和过程等。

视图使用一个无效视图自动会导致Oracle动态编译这个视图。替换这个视图后,视图可能是有效,也可能是无效的,这跟下列情况有关:

视图查询定义中引用的基表必须存在。如果视图的基表重命名或者删除了,视图就是无效的,无法使用。引用一个无效视图会导致引用语句失败。只有基表重新命名为原始名称或者重新创立基表视图才能被编译。

如果基表被修改或者使用同样列名创建,但是基表中一个或者多个列的数据类型改变了,然后大部分依赖视图可能成功的重新编译。

如果视图的基表被修改或者使用至少相同系列的列重建,然后视图可以是有效的。如果基表使用新列重建而且视图引用的列不再包含在重建表中,视图是无效的。最后一个相关情况是在SELECT * FROM table定义的视图,因为定义在视图定义时被扩展,并持久的保存在数据字典中。

程序单位和引用对象

当引用对象修改之后,Oracle自动将程序单位失效。例如,假定一个单独过程包含多个语句引用了表、视图、其他的单独过程、公用包过程。在那种情况下,会发生:

如果引用表被修改,然后依赖过程无效

如果引用视图的基表被修改,视图和依赖过程都无效

如果引用的单独过程被替换,然后依赖过程无效

如果包体的引用被替换,那么依赖过程就不受影响。但是,如果引用包的定制被替代,那么依赖过程就无效了。这是在一种最小化过程和包引用的对象之间依赖的机制。

无论何时你创建了一个表、索引、视图和删除表,依赖于表的所有对象都失效,包括视图、包、包体、函数和过程在内。

数据仓库的考虑

某些数据仓库晚上会删除表的索引来加快事实表的装载速度。但是基表的索引被删除,所有依赖视图都会失效。这意味着其后运行的引用这些视图的包都无效。

记住无论何时,你创建了表、视图、然后删除索引,依赖表的所有的对象都会失效,包括视图、包、包体、函数、过程。这保护了可更新关联视图。

要是的视图重新生效,使用下列语句之一:

SELECT * FROM vtest;

或者

ALTER VIEW vtest compile;

会话状态和引用包

每个引用一个包结构的会话都有自己的包实例、包括任何公用和私用变量的持久性状态、游标和常量。所有的会话包实例包含的状态在会话的实例包无效和重新编译之后会丢失。

安全认证

当一个DML对象或系统权限分配给一个用户或PUBLIC或回收权限时,Oracle会注意到,自动将所有拥有者的依赖对象失效。Oracle将依赖对象失效是为了验证依赖对象的拥有者还拥有所有引用对象的必须权限。本质上说,Oracle注意到那些不需要重新编译的对象。只有安全认证需要确认,并不是任何对象的结构需要确认。这种优化降低了不必要的重新编译,阻止不必要的修改依赖对象的时间戳。

对象名称解决

SQL语句中引用的对象名称按照周期分为几个部分。下面描述了Oracle如何解析对象名称:

1、Oracle尝试在SQL语句中限定第一部分的引用名称。例如,在hr.employees,hr是第一部分。如果只有一部分,那么这部分就是第一部分。

a. 在当前模式下,Oracle搜索名称符合对象名称的第一部分的对象。如果没有找到这样的对象,然后转向步骤b。

b. Oracle查找公用同义词来匹配名称的第一部分。如果没有找到,然后转向步骤c。

c. Oracle查找一个模式名字匹配对象名字第一部分的模式,如果找到了,然会步骤b,现在使用名称第二部分在匹配模式中寻找。如果第二部分不能在前面匹配的模式中找到对象,或者没有第二部分,Oracle会返回一个错误。

如果步骤c无法找到模式,那么对象无法匹配,Oracle返回一个错误。

2、模式对象已经匹配,任何剩余的名字部分都要匹配找到的对象的有效部分。例如,如果hr.employees.department_id是名字,然后hr作为模式匹配,employees匹配表,department_id必须对对应列(因为employees是表)。如果employees匹配一个包,那么department_id必须对应一个那个包的公用常量、变量、过程或函数。

因为Oracle解决引用的方式,很可能一个对象依赖于其他不存在的对象。依赖对象使用的引用采取不同的翻译方式就会是另一个对象,就有可能发生这种情况。

共享SQL依赖管理

在模式对象之间的依赖管理之外,Oracle还在共享池中管理每个共享SQL区域的依赖。如果一个表、视图、同义词或者序列被创建、修改或删除、或者一个过程或包规范被重新编译,所有依赖它们的共享SQL区域都无效。在对应于一个无效共享SQL区域的游标的随后执行中,Oracle会重新分析SQL语句来产生新的共享SQL区域。

本地和远程依赖管理

依赖跟踪和完成必要的重新编译是Oracle自动执行的,本地依赖管理指的是Oracle在单独数据库中对象中管理依赖。例如,一个过程中的语句能够引用同一个数据库的表。

远程依赖管理指的是Oracle跨网络在一个分布式环境中管理依赖。例如,一个Oracle表格触发器可以依赖数据库中的一个对象。在分布式环境中,一个本地视图定义的查询可以引用远程表。

管理本地依赖

Oracle使用数据库内部依赖表来管理所有的本地依赖,内部依赖表保存了每个模式对象的依赖对象。当一个引用对象被修改,Oracle使用依赖表来标识依赖对象,这些对象被标识为无效。

例如,假设一个存储过程UPDATE_SAL引用了表JWARD.employees。如果表的定义被以任何方式修改,每个引用JWARD.employee的对象状态都改为INVALID,包括存储过程UPDATE_SAL。因此,这个过程不能运行 ,直到它被重新编译状态变为有效为止。类似的,当一个用户被撤销了DML权限,用户模式下的每个依赖对象都无效。但是,一个由于认证被撤销导致的对象失效只要重新认证就可以重新生效,在这种情况下,不需要全部重新编译。

管理远程依赖

Oracle还管理应用对数据库和分布数据库的依赖。例如,一个Oracle表格应用程序可能包含一个触发器,触发器指向一个表,或者一个本地存储过程可能调用在一个分布式数据库环境中的过程。数据库环境必须说明这些对象之间的的依赖。Oracle根据包含对象的不同,使用不同的机制来管理远程依赖。

本地和远程数据库过程之间的依赖

在分布式数据库环境中的存储过程、函数、包、触发器之间的依赖使用时间戳校验或签名校验。

动态初始化参数REMOTE_DEPENDENCIES_MODE指定是否时间戳或签名管理远程依赖。

时间戳管理

在时间戳校验依赖模型中,无论合适一个过程被编译或者重新编译,它的时间戳(创建、修改和替代的时间)在数据字典中都会保存。时间戳是记录过程创建、修改和替代的时间。另外,过程的编译版本包含它引用的每个远程过程的信息,包括远程过程的模式、包名称、过程名称和时间戳。

当使用了一个依赖过程,Oracle将远程引用过程的当前时间戳和编辑时保存的远程时间戳。依据这种比较,会发生两种情况:

如果时间戳匹配,本地和远程过程不需要编译,直接运行

如果远程引用过程时间戳不匹配,本地过程无效,调用环境返回一个错误。此外,所有其他依赖远程的新时间戳过程的本地其他过程都无效。例如,假设多个本地过程调用一个远程过程,而远程过程重新编译了。当一个本地过程运行,并注意到远程过程的不同时间戳,每个依赖远程进程的本地过程都无效。

在本地过程体的语句中调用远程过程时发生实际时间戳比较。只有在这个时候,时间戳比较才使用分布式数据库的通讯连接。因而,先于无效过程的本地过程的所有语句可以成功运行。无效过程调用的随后的语句无法运行。需要重新编译。

依赖于如何调用无效过程,在无效过程调用之前的DML语句需要回滚。如下所示,随着整个PL/SQL块改变被回滚,UPDATE结果也被回滚。

BEGIN

UPDATE table set ...

invalid_proc;

COMMIT;

END;

但是,如下所示,UPDATE结果是正常的,之后PROC调用被回滚。

UPDATE table set ...

EXECUTE invalid_proc;

COMMIT;

签名校验

Oracle使用签名来提供远程依赖的额外能力。签名能力只影响远程依赖。本地依赖是不受影响的,因为这种情况下总可能重新编译。

过程的签名包含下列项的信息:

包、过程或函数的名称

参数基本类型

参数样式(IN、OUT、IN OUT)

注意:只有参数的类型和样式是有意义的。参数的名字不影响签名。

如果签名依赖模式起作用了,如果依赖单位包含一个父单位中的一个过程的调用,并且这个过程的签名以一种不兼容的模式修改了,对于远程程序单位的依赖会导致依赖单位的无效。程序单位可以是包、存储过程、存储函数或者触发器。

其他远程模式对象的依赖

Oracle并不管理远程模式对象的依赖,只管理本地过程到远程过程的依赖。

例如,假设本地视图被创建,定义中的查询引用了一个远程表。还假设本地过程包含的SQL语句引用了同名的远程表。然后,表的定义被修改。

因此,本地视图和过程无法生效,即视图或过程在表被修改之后使用,甚至现在使用视图或过程还会返回错误。在这种情况下,视图或过程必须手动修改,这样才不会返回错误。在这种情况下,依赖管理的不足会导致不必要的重新编译依赖对象。

应用程序依赖

数据库应用程序的代码可以指向连接数据库引用的对象。例如,OCI和预编译应用程序可以提交匿名PL/SQL块。Oracle表格应用程序的触发器可以指向一个模式对象。

这些应用程序依赖它们引用的模式独享。依赖管理技术根据开发环境而不同。

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值