【发布时间】:2011-04-18 22:41:01
【问题描述】:
嗨 我们有一个第三方基于 oracle 的应用程序,它附带预编译的二进制(包装)包。 但是当我在 Oracle SQL Developer 中编译它们时(右键单击 -> 全部编译),它们就会失效。
重新编译是否安全且无副作用的操作?
【问题讨论】:
-
不是真的——除非你知道它是如何编译的。这是一个问题 - 如果它有效,你为什么要编译它?
嗨 我们有一个第三方基于 oracle 的应用程序,它附带预编译的二进制(包装)包。 但是当我在 Oracle SQL Developer 中编译它们时(右键单击 -> 全部编译),它们就会失效。
重新编译是否安全且无副作用的操作?
【问题讨论】:
大多数第三方应用程序建议您不要编辑/编译他们的对象,除非他们的支持当然告诉您这样做。
由于你不知道所有的依赖对象,我建议你在修改他们的对象之前先联系第三方应用程序的支持团队。如果它是捆绑应用程序,简单地重新编译 oracle 对象可能会使其他层中的依赖应用程序/服务无效。
【讨论】:
主要的副作用是,如果您编译另一个包所依赖的包,则可能会使任何现有会话的依赖包无效——即使编译没有错误。这对于会话短暂的应用程序来说很好,但对于会话长期存在的应用程序来说,这是一个问题。如果您在 JDBC 中使用连接池,则缓存的会话将长期存在并且可能会失效。您必须刷新缓存的会话以避免错误。
您要查找的错误是“ORA-04068: 包的现有状态已被丢弃”。
请参阅here 了解更多信息。
特别是关于 SQL Developer - 它不能很好地处理包装包的重新编译。如果您要重新编译它们,请尝试使用其他工具,如 TOAD 或 PL/SQL Developer,或使用 SQL Plus 命令行中的“alter package”命令。
【讨论】:
如果您的软件包无效,它们是否真的无效,因为它们将不再工作? 尝试使用 sqlplus 重新编译无效的包体。
SQL>alter package <package name> compile body;
如果您收到“编译错误”的消息
SQL>show errors;
这将提供有关错误的一些信息。
一般来说,重新编译包装好的包是可以的。应该不是问题。
【讨论】:
就我个人而言,我会避免“重新编译所有”(在 SQL Developer 或 TOAD 中)——尤其是在您从其他用户或软件打开数据库连接的任何环境中。
在大多数情况下,您可能只想重新编译无效对象。
如果您使用的是 Oracle 10 或更高版本,则有两个内置软件包可以执行此操作(尽管您的角色可能无法在不与您的 DBA 交谈的情况下访问它们)。
UTL_RECOMP.RECOMP_PARALLEL(threads => 4, schema => :schema_owner)
DBMS_UTILITY.COMPILE_SCHEMA(schema => :schema_owner, compile_all => FALSE)
UTL_RECOMP 是新的首选方式。 DBMS_UTILITY 存在于早期版本的 Oracle 中,但总是会编译所有内容 - compile_all 是一个新的可选标志,它让我们告诉它只编译无效项。
如果您使用的是早于 10 的版本,我建议您使用自己的编译无效程序 - 我发现将其编写为可以通过 DBMS_JOB 提交的作业,然后通过 DBMS_SMTP(DBMS_MAIL 在奥拉 10)。
我的工作递归地尝试编译所有依赖项都有效的无效对象,使用以下 SQL,直到迭代之间没有更改。
SELECT uo.object_name,uo.object_type
FROM user_objects uo
WHERE uo.status = 'INVALID'
MINUS -- objects with invalid children
SELECT uo.object_name,uo.object_type
FROM user_objects uo,
user_objects uo2,
public_dependency pd
WHERE uo.status = 'INVALID'
AND uo.object_id = pd.object_id
AND pd.referenced_object_id = uo2.object_id
AND uo2.status = 'INVALID'
【讨论】: