【问题标题】:PL/SQL invalidationPL/SQL 失效
【发布时间】:2014-05-12 16:37:30
【问题描述】:

我有一个 JDBC 会话引用 PL/SQL 包的场景。当我更改包主体并重新编译它时,会话不会引发任何异常,但是当我重新编译包规范时,它会引发以下异常。我的问题是为什么当包体更改时会话不会抛出任何异常,如果我在包体中进行更改,现有会话会看到更改吗?

ORA-04068: existing state of packages has been discarded

【问题讨论】:

    标签: oracle plsql


    【解决方案1】:

    如果 PL/SQL 包具有全局变量(常量或可修改),则认为该包具有状态。如果更改包,变量会重新初始化并且状态会丢失。

    如果一个数据库会话已经使用了这个包,它在下次访问这个包时会得到一个 ORA-04068 异常。如果它处理了异常,则它可以继续使用该包而不会再次收到异常。当然,状态丢失,应用新版本的包。

    对于没有全局变量的 PL/SQL 包,不会引发错误。新版本的软件包立即适用于所有会话。

    那么,如果更改后的包不再在该会话中使用,您为什么希望该会话抛出异常?这会导致比增加价值更多的问题。

    【讨论】:

    • 常量不会导致这个from 11.2.0.2。该“新功能”部分还链接到包状态的文档。
    • 你说对于没有全局变量的PL/SQL包,不会抛出错误。软件包的新版本立即适用于所有会话。这不是真的。为此,您必须将包的状态更改为 PRAGMA SERIALLY_REUSABLE
    【解决方案2】:

    阅读Reasons to use Packages中的“更简单的应用程序设计”和“隐藏的实现细节”部分

    包编写指南”部分(同一页)中的所有文档都明确指出:

    在包装规范中,仅声明必须对 调用程序。

    这种做法可以防止其他开发人员构建不安全的 依赖于您的实现细节并减少对 重新编译。

    如果你改变包规范,你必须重新编译任何 调用包的公共子程序的子程序。如果你 只改变包体,你不需要重新编译那些 子程序。

    【讨论】:

      【解决方案3】:

      这是一个众所周知的问题。 在这里你可以找到如何解决它的任何细节。 http://laurentschneider.com/wordpress/2010/12/how-to-solve-ora-4068.html.

      但是如果你对全局变量要非常小心!如果它们在你的包中使用,那么当其他程序正在使用它时不要编译你的包。

      从 dba 的角度来看,通过 v$access 视图可以知道谁拥有这个包的“锁”。因此,您可以通过 ddl 上的触发器引发编译。

      【讨论】:

        猜你喜欢
        • 2011-01-30
        • 2021-05-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-08-30
        相关资源
        最近更新 更多