2009年2月12日星期四

依赖性 dependencies among schema objects

某些类型的方案对象可以在其定义中引用其他对象。例如:视图的定义就是一个引用了其他表或视图的查询;一个过程中也可以包含引用了其他数据库对象的SQL语句。如果一个对象的定义中引用了其他对象,那么这个对象被称为依赖对象(dependent object),此对象所引用的对象被称为被引用对象(referenced object)。
如果用户修改(alter)了一个被引用对象(referenced object)的定义,则相应的依赖对象(dependent object)是否能够正常工作将取决于修改该的类型。例如:如果用户移除(drop)了一个表,那么所有基于此表的视图将失效。
oracle能够自动地记录对象间的依赖关系,以便降低依赖性管理的复杂程度,减轻数据库管理员和用户的工作负担。例如,一个表被多个过程所引用,当用户修改了被引用表(referenced table)的定义后,oracle将在依赖过程(dependent procedure)下一次被引用时自动地将其重新编译(recompile)。
为了管理方案对象间的依赖关系,oracle需要记录所有的方案的状态(status):
有效的(valid)已经通过编辑,可以在被引用时直接使用
无效的(invalid)必须在使用之间进行编译。对于过程(procedure)、函数(function)、包(package)来说,这意味着对其进行编译。对于视图来说,这意味着此视图必须使用被引用对象(referenced object)当前在数据字典中的定义信息(current definition)重新进行语法分析。
只有依赖对象(dependent object)可以处于无效(invalid)状态。表(table)、序列(sequences)和同义词(synonyms)总是处于有效状态(valid)。
如果一个视图(view)、过程(procedure)、函数(function)或包(package)处于无效状态,oracle会尝试对其进行重新编译,但是这个过程可能会发生错误。例如,当编译一个视图时,此视图的基表(base table)有可能不存在,或访问基表的权限不存在;当编译一个包时,有可能出现PL/SQL或SQL语法错误、或访问被引用对象(referenced object)的权限不存在。在编译时发生此类问题的方案对象(schema object)将保持无效状态。
oracle能够自动地跟踪数据库中发生的特定变化,并在数据字典中记录相关的方案对象的最新状态。
状态记录时一个递归过程。被引用对象(referenced object)的状态变化不仅对导致其直接依赖对象(directly dependent object)的状态变化,同时会影响其间接依赖对象(indirectly dependent object)的状态。
例如:当一个存储过程引用了一个视图的时候,这个存储过程间接的引用了此视图的基表。
一、解析方案对象的依赖性(resolution of schema object dependencies)
当一个方案对象(schema objcet)在SQL语句中被直接引用或被此语句中的依赖对象(dependent object)所引用(或间接引用)时,oracle均会在需要时对其状态进行检查。SQL语句中被直接或间接引用的对象的状态决定了oracle的后续操作。
如果SQL语句中所有的被引用对象(referenced object)均处于有效状态,则oracle无需进行其他工作就可以直接执行SQL语句。
如果SQL语句中引用的任何视图、PL/SQL程序结构(过程procedure、函数function、包package),oracle将自动地尝试编译这些对象。如果所有的无效的被引用对象(referenced object)都能被成功编译,则oracle将在编译后执行SQL语句。如果一个方案对象不能被成功编译,那么它将继续保持无效状态。oracle回滚执行失败的SQL语句并返回一个错误信息。事务(transaction)中已经成功的操作由用户决定是进行提交还是回滚。
如果一个方案对象在处于无效状态之后被用户替换(replace)掉,则oracle不会对其进行重新编译。这项优化错误减少了不必要的重新编译操作。
1、编译视图及PL/SQL程序结构
当满足以下条件时,视图及PL/SQL程序结构可以被编译并置为有效状态:
视图或PL/SQL程序结构的定义必须正确。SQLj及PL/SQL语句的语法结构必须正确。
所有被引用对象(referenced object)及其结构必须满足定义的要求。例如:如果视图的定义查询(defining query)中引用了某列,那么此列必须存在于基表(base table)中。
视图或PL/SQL程序结构的所有者必须具备访问引用对象的权限。例如:过程中的一个SQL语句向某个表中插入一条数据,那么此过程的所有者必须具备对被引用表(referenced table)的INSERT权限。
注:如果一个视图所引用的基表或其他视图被修改(alter)、重命名(rename)或移除(drop)后,此视图将被置为无效状态,但是这个视图的定义仍被保存于数据字典内,相关的权限信息,引用此视图的同义词(synonyms)、对象,及其他视图也都会被保留(虽然视图处于无效状态,但是这个视图的定义还是存在的)。
当用户需要使用一个处于无效状态的视图时,oracle会在运行时自动重新编译此视图。而当一个视图被替换(replace)后,其有效性由以下条件决定:
视图的定义查询中所引用的全部基表(base table)必须存在。如果视图所引用的一个基表被重命名(rename)或被移除(drop),视图将被置为无效状态且不可用。引用无效视图的语句将会失败。只有当基表恢复原名或重建视图才能被成功编译。
如果基表被修改或重建(re-created)后保留了原来的全部列,但是某些列的数据类型发生了变化,那么大部分依赖视图能够被成功地重新编译。
如果视图的基表被修改或重建后保留了原来的全部列,那么此视图的状态仍为有效。如果重建的基表中不再包含视图所引用的列,那么此视图的状态将被置为无效。如果视图时使用SELECT * FROM table形式的语句定义的,常会导致上述情况中的后者出现,因为在视图创建时其定义查询(defining query)将被扩展到基表的所有字段并永久存储于数据字典中。
二、解析方案对象名称
在SQL语句中引用的方案对象名称可由多段(piece)组成,各段之间使用“.”分隔。以下内容描述了oracle如何就解析对象名称:
1、oracle首先验证SQL语句中所引用的对象名称的首段。例如在hr.employees中,hr位首段。如果引用的名称只由一段构成,则此段就被看作时首段。
a、oracle首先在当前方案中搜索名称与对象名首段相符的对象。如果不存在则进入到步骤b。
b、oracle搜索名称与对象名称首段相符的公有同义词(public synonym)。如果不存在,则进入到步骤c。
c、oracle搜索名称与对象名称首段相符的方案,如果找到这样一个方案,则返回步骤b,使用对象名称的第二段在方案中搜索相符的对象。如果方案中不存在相符的对象,或引用的对象名称只由一段构成,则oracle将返回一个错误。
注:如果在步骤c中没有找到相符的方案,那么引用的对象名称也不能被验证,oracle将返回一个错误。
2、如果数据中存在语句中所引用的方案对象,这个方案对象还必须具备对象名称剩余段所代表的内容。例如:当引用名称为hr.employees.department_id时,如果hr代表方案名称,employees代表表名,那么department_id必须与employees表中的某个列名称相符;如果employees代表包名称,那么包内必须存在名为department_id的公有常量、变量、过程或函数。
三、共享SQL的依赖性管理
oracle 除了需要管理方案对象的依赖性,还需要管理共享池(shared pool)中各个共享SQL区(shared SQL area)的依赖性。如果用户创建、修改或移除了表、索引、同义词或序列,或者重新编译了包、或包声明,那么所有依赖共享SQL区都将被置为无效。当一个基于无效共享SQL区的游标继续执行时,oracle将重新对SQL语句进行语法分析,并生成新的共享SQL区。
四、本地及远程依赖性管理
监控数据库内的依赖性以及进行必要的重编译都是由oracle自动地执行的。本地依赖性管理(local dependency management)是指oracle管理一个单一数据库内各个对象间的依赖关系。例如:某过程内的一个SQL语句引用了相同数据库中的一个数据表。
远程依赖性管理(remote dependency management)是指oracle管理一个分布式环境内的各种依赖关系。例如:一个oracle forms触发器可以依赖于一个数据库内的方案对象;在一个分布式数据库内,一个本地视图的定义查询可以引用一个远程表。
1、本地依赖性管理
oracle使用数据库内部的依赖性关系表(dependency table)来管理所有的本地依赖性,依赖关系表用于记录每个方案对象的依赖对象(dependent object)。当用户修改了一个被引用对象(referenced object),oracle就会使用依赖关系表确定此对象的所有依赖对象,并将它们全部置为无效状态。
例如:假设存储过程UPDATE_SAL引用了JWARD.employees表。当JWARD.employees表的定义被修改后,所有引用此表的对象都将被置为INVALID,包括存储过程UPDATE_SAL。此存储过程必须经过重新编译并置为有效状态后才能再次运行。同样,当一个用户所拥有的对象权限(DML privilege)被撤销(revoke)后,此用户方案内的所有依赖对象也将被置为无效状态。但在后面这种情况中,由于使对象无效的原因使授权(authorization)被撤销,因此可以通过重新授权(reauthorization)使对象恢复有效状态,此时无需对无效对象进行重新编译操作。
2、远程依赖性管理
oracle还要管理应用程序与数据库间的依赖关系,以及分布式数据库间的依赖关系。例如:oracle forms应用程序可以使用一个引用了数据表的触发器;本地的存储过程也可能调用分布式数据库系统中的远程过程。数据库系统必须能够管理此类对象间的依赖关系。oracle根据对象的不同而选择不同的机制来管理远程依赖性。

没有评论:

发表评论