为啥我的Java应用程序每次编译完数据库包后都需要重启?

Posted

技术标签:

【中文标题】为啥我的Java应用程序每次编译完数据库包后都需要重启?【英文标题】:Why does my Java application need to be restarted every time after the database package is compiled?为什么我的Java应用程序每次编译完数据库包后都需要重启? 【发布时间】:2015-04-09 04:11:53 【问题描述】:

我正在我的应用程序中调用 Oracle 数据库包。如果我重新编译那个包,那么我的应用程序需要重新启动,否则它会说代码已修改。

谁能解释一下为什么会这样?

【问题讨论】:

你说的数据库包是指PLSQL吗?如果是这样,这可能是 Oracle 的一个问题。否则你能解释一下吗? 您的包是否使用包范围的变量?然后这些变量引用在重新编译包时变得无效。手册中的更多详细信息:docs.oracle.com/cd/E11882_01/appdev.112/e25519/… 【参考方案1】:

Oracle 包可以包含状态信息。在包的主体中,您可以在包级别定义变量。这些“全局变量”存在于对数据库的调用之间,并与数据库会话相关联。当包被重新编译时(我猜这就是你在错误中看到的“已修改”)你可能已经从包体中添加或删除了变量,所以 Oracle 必须丢弃包的旧状态并制作一个新鲜的。它通过引发 ORA-04068: Existing state of packages has been discarded 警告您这样做。

如果您使用某种连接池(包括Database Resident Connection Pooling),这在网络服务器上很常见,您需要记住,当您在代码中关闭连接时,连接并没有真正关闭。它只是在应用服务器完成后(通过调用 Closed、Dispose 等)返回到池中,但它保持打开状态,Oracle 数据库不会注意到您认为它“关闭”。当需要新连接时,它会从池中获取旧连接并将其提供给服务器。由于 Oracle 从未关闭连接,因此会话从上次使用时起仍然处于活动状态。如果自从上次使用连接后包被更改,您仍然可以获得 ORA-04068,即使您的代码看起来像是刚刚打开了一个全新的连接。重新启动您的应用程序服务器将导致池中的所有连接在关闭时关闭并在启动时重新创建,这似乎是您现在解决问题的方式。

如果可以的话,最好的选择是使用edition based redefinition。这样您就可以编译新包,但只有新会话才会使用新代码。旧会话将继续使用旧代码。同样,如果您正在做诸如错误修复之类的事情,这可能并不理想,因为您在旧会话替换新会话之前,他们会接受修复。

第二种选择是,如果您知道您不在乎该特定包的内部状态是否丢失,则只需再次运行包过程/函数调用。 Oracle 不会再给你 ORA-04068(除非再次重新编译包)。

希望这会有所帮助。如果不是有关您看到的确切错误和您的环境的更多详细信息,将会很有帮助。

【讨论】:

谢谢它帮助了我。但我不清楚第二个选项。这些线索将我带到下面的链接,真的很有帮助。markhoxey.wordpress.com/2013/09/17/… 那篇文章对这个问题很有帮助。对于第二个选项,我只是说在重新编译后你只会得到一次 ORA-04068。因此,如果您要从 Java 调用 proc 并在错误是 ORA-04068 时捕获异常,您应该能够重复完全相同的调用并让它这次工作。不是最干净的解决方案,但它会起作用。此外,如果您在此页面上看到的任何回复有帮助,请投票给答案。谢谢!【参考方案2】:

据我所知,您不需要重新启动应用程序,只需重新创建与数据库的连接,这是因为驱动程序在内存中保存了与您的包的先前编译版本的链接,因此新的连接将获取更新版本。它通常在 PLSQL/Oracle 数据库上观察到,它与驱动程序有关,与 Java 无关。 看看这个问题/答案,Does Tomcat use cached versions of pl/sql modules?,它对如何克服这种情况有一些建议。

希望对你有帮助!

【讨论】:

【参考方案3】:

在重新编译该包后刷新共享池会有所帮助,因为它会强制连接的会话在共享池刷新后第一次尝试访问该包时进行重新解析。

具有 DBA 权限: alter system flush shared_pool;

请注意,其他应用程序在刷新共享池后可能会在一段时间内遇到一些缓慢,因为它们连接的会话也将被强制重新解析其 SQL/PLSQL 语句,因此建议与包重新编译一起计划在高峰时间刷新共享池。

【讨论】:

以上是关于为啥我的Java应用程序每次编译完数据库包后都需要重启?的主要内容,如果未能解决你的问题,请参考以下文章

我用虚拟机使用centos linux 每次输了login和password后都提示login incorrect。这是为啥?怎么解决?

为啥安装完tomcat 以后,每次启动都是拒绝访问,急需答案!

我的codeblocks为啥运行不了?

我用虚拟机使用centos linux 每次输了login和password后都提示login incorrect。这是为啥?怎么解决?

VS2013每次打开一次后都必须重启

java为啥每次都是找不到文件。找不到文件?