ORA-04061: 包体 "PACKAGE.NAME" 的现有状态已失效仍然存在

Kam*_*ora 4 oracle plsql oracle11g oracle12c

在我正在处理的 Oracle 数据库实例之一上,我在重新编译包时观察到与正常行为不同的行为。

通常,(如Oracle ORA-04068 中的常见错误:包的现有状态已被丢弃)在 PL/SQL 包重新编译后首次调用时会出现以下错误:

ERROR at line 1:
ORA-04068: existing state of packages has been discarded
ORA-04061: existing state of package body "PACKAGE.NAME" has been
invalidated
ORA-06508: PL/SQL: could not find program unit being called:
"PACKAGE.NAME"
ORA-06512: at line 1
Run Code Online (Sandbox Code Playgroud)

但是第二次调用应该可以正常工作,假设包当然没有错误。此行为以前在该环境中存在。与此同时,我们从 11g R2 升级到 12c R1,并启用了基于版本的重新定义。

现在我遇到的问题是我不断得到:

ORA-04061: existing state of package body "PACKAGE.NAME" has been
invalidated
ORA-06508: PL/SQL: could not find program unit being called:
"PACKAGE.NAME"
ORA-06512: at line 1
Run Code Online (Sandbox Code Playgroud)

所以不再有 ORA-04068,修复它的唯一方法是重新连接会话或手动调用 DBMS_SESSION.RESET_PACKAGE()(但我无法控制所有可能受到影响的代码),否则每次调用时问题仍然存在。

是否有任何 DB 参数可以控制可以进行调整?该问题并非特定于任何特定的 PL/SQL 包,似乎它可以在它引用的某些内容发生更改时由正常的包失效触发。

先感谢您。

APC*_*APC 5

Oracle 这样做是因为重新编译 PL/SQL 包会使任何正在使用的会话变量无效。

除了使用良好的部署实践之外,我们无法避免这种情况。不要在使用数据库时部署更改,确保所有连接都正确断开等。在这个 CI/CD、零停机时间和其他令人兴奋的创新时代说起来容易做起来难。

所以在储物柜的后面有一个东西:pragma serially_reusable;。此指令意味着在单个服务器调用期间保持包的状态。例如,如果我们有一个 PL/SQL 块,它调用 SR 过程三倍,该过程更改的任何变量将在三个调用中主值。但是下次我们运行块时——在同一个会话中——变量将被重置为它们的起始值。

串行可重用 PL/SQL 有几个限制——例如,它不能用于 SQL 查询。但从您的角度来看,最大的吸引力在于不再有 ORA-04068 或 ORA-04061 错误。没有会话状态,没有什么可以失效的。

pragma serially_reusable必须在包级别、正文和规范中声明。因此,您必须确保所有打包的过程都不需要跨服务器调用维护状态。