我正在我的应用程序中调用 Oracle 数据库包。如果我重新编译该包,那么我的应用程序需要重新启动,否则它会说代码已修改。
谁能向我解释一下为什么会发生这种情况?
最佳答案
Oracle 包可以包含状态信息。在包的主体中,您可以在包级别定义变量。这些“全局变量”存在于对数据库的调用之间,并且与数据库 session 相关联。当重新编译包时(我猜这就是您在错误中看到的“已修改”),您可以在包主体中添加或删除变量,因此 Oracle 必须丢弃包的旧状态并进行更改新鲜的。它警告您,它通过引发ORA-04068:现有的包状态已被丢弃来做到这一点。
如果您正在使用某种类型的连接池(包括 Database Resident Connection Pooling )(这在 Web 服务器上很常见),您需要记住,当您在代码中关闭连接时,连接并没有真正关闭。当应用程序服务器完成使用它(通过调用 Closed、Dispose 等)时,它只是返回到池中,但它保持打开状态,Oracle 数据库不会注意到您认为它“已关闭”。当需要新连接时,它从池中获取旧连接并将其提供给服务器。由于 Oracle 从未关闭过连接,因此 session 自上次使用以来仍然处于 Activity 状态。如果自上次使用连接后程序包发生了更改,您仍然可以获得 ORA-04068,即使您的代码看起来像是刚刚打开了一个全新的连接。重新启动应用程序服务器将导致池中的所有连接在关闭时关闭并在启动时重新创建,这似乎就是您现在解决问题的方式。
如果可以的话,最好的选择是使用 edition based redefinition 。通过这种方式,您可以编译新包,但只有新 session 才会使用新代码。旧 session 将继续使用旧代码。同样,如果您正在做错误修复之类的事情,这可能并不理想,因为在旧 session 修复新 session 之前,您将受到旧 session 替换新 session 的支配。
第二个选择是,如果您知道自己不关心该特定包的内部状态是否丢失,则只需再次运行包过程/函数调用。 Oracle不会再给你ORA-04068(除非再次重新编译包)。
希望这有帮助。如果不是有关您看到的确切错误和您的环境的更多详细信息,将会有所帮助。
关于java - 为什么我的Java应用程序每次编译数据库包后都需要重新启动?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29529617/