【问题标题】:How is stateful pl/sql package defined?有状态的 pl/sql 包是如何定义的?
【发布时间】:2014-01-08 08:06:08
【问题描述】:

我的 java 用户收到“找不到单元”错误,但我的包是有效的。 另一篇文章提出了根本原因:我的包不能是无状态的。这是有道理的,但我不清楚 Oracle 对无状态的真正定义:

如果我从包的 SPEC 中删除所有声明的类型,它是否有资格成为无状态,还是我还必须从主体中删除所有 GLOBAL 变量?

以下是 Oracle 对无状态的定义:

“包声明的变量、常量和游标的值(在其规范或主体中)构成了它的包状态。如果 PL/SQL 包声明了至少一个变量、常量或游标,那么包是有状态的;否则,它是无状态的。”

这与这篇文章中提出的问题相同:

ORA-06508: PL/SQL: could not find program unit being called

【问题讨论】:

  • 如果应用打开了一个活动会话,并且调用了以前引用的包,同时有人重新编译了包,就会发生这种情况。你做了很多重新编译吗?
  • 下面的答案总结得很好,但要点是包部署应该与应用程序部署绑定。

标签: java sql oracle plsql


【解决方案1】:

如果我从包的 SPEC 中删除所有声明的类型,它是否符合无状态,或者我还必须从主体中删除所有 GLOBAL 变量?

从身体也是如此。规范中声明的变量(或常量,或类型等)与正文中声明的变量(或常量,或类型等)的唯一区别是,正文中的变量是私有的,只能在正文中引用,而规范中的变量是可以看到和看到的。外用。

documentation 还提到编译时常量不会使包从 11gR2 开始成为阶段性的,但因为您谈论的变量可能不太有用。

(希望“全局”只是指在过程或函数之外声明的变量;这些变量仍仅限于单个会话,它们不是跨会话的全局变量,因为该标签 可能 暗示)。

您可以在运行程序遇到错误之前重置任何 JDBC 连接,这将使它们继续运行,但这取决于您在做什么。例如,在 WebLogic 中,在重新编译有状态包后,我可以重置连接池,这会关闭所有现有连接并打开新连接 - 这些连接具有新的会话,因此具有新的包实例化。

如果会话确实遇到错误,并且没有因此终止,那么该会话中的下一个包调用应该获取包的新版本并继续;但这仍然可能是一个有副作用的问题。虽然如果你有一个连接池,同一个程序可能会多次看到错误,因为它不断从池中获取新连接,并且它的会话遇到状态问题。最终,池中的所有连接都应该得到一个新版本,或者被终止并替换。

正如@pedantic 评论的那样,我没有说明清楚,这仅适用于短而重复的更新周期使其成为必要的开发环境;即使使用无状态包,您也不应该在使用实时系统时将更改部署到它。

【讨论】:

  • Alex,我们经常被要求“scrum”更新到生产环境,而部署更新的过程会导致包状态错误。此时我只是重启服务器,重置连接池。 。你得到你想要的。 :)
  • 是的,这一切都很好,除非您永远无法关闭系统,并且正在运行依赖于您的 Oracle 包的 7by24 数据服务.. 这是我的情况。我们必须将所有数据服务流量重新定向到故障转移 Oracle 主机,进行重新编译,然后将它们全部移回主服务器,这是一个很大的痛苦。如果它们存在的话,我正在寻找更优雅的方法这没有冲洗池.. java 人也不太欣赏.. 感谢您的好主意 - 非常感谢!
  • 现在,回到无状态包定义:如果我在过程和函数之外同时取出规范和主体类型声明,那会使其无状态吗? “全局”是指包主体的全局,而不是跨 Oracle 会话,不是 SGA 中的全局上下文,不是那个……抱歉,我在这方面有点慢……非常感谢您的建议!
  • 重新编译会污染包状态。
  • @user3119949 - 规范或正文中的类型声明不会使其成为有状态的。是的,我意识到实时更新可能有操作原因,应该避免它们是可能的(无论如何,IMO)。有时你只需要在强加给你的约束范围内做你能做的事情。无论如何...this might be useful 在部署之前检查问题。
猜你喜欢
  • 1970-01-01
  • 2019-05-19
  • 1970-01-01
  • 1970-01-01
  • 2020-08-13
  • 2010-09-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多