为什么每次编译数据库包后都需要重新启动我的Java应用程序?

时间:2015-04-09 04:11:54

标签: java web-applications oracle11g

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

有人可以向我解释为什么会这样吗?

3 个答案:

答案 0 :(得分:1)

Oracle包可以包含状态信息。在包的主体内,您可以在包级别定义变量。这些“全局变量”存在于对数据库的调用之间,并与数据库会话相关联。当重新编译包时(我猜这是你在错误中看到的“修改过的”)你可以在包体中添加或删除变量,因此Oracle必须抛弃包的旧状态并使一个新的。它警告你它通过提高 ORA-04068来实现这一点:已丢弃现有的包状态

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

  • 如果可以,最好的选择是使用edition based redefinition。这样您就可以编译新包,但只有新会话才会使用新代码。旧会话将继续使用旧代码。再次,如果你正在做一些像bug修复这样的事情,这可能并不理想,因为你会受到旧会话的支配,取代新的会议才能获得修复。

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

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

答案 1 :(得分:0)

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

希望它有所帮助!

答案 2 :(得分:0)

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

具有DBA权限: alter system flush shared_pool;

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