当我使用异常处理程序时,在第二次尝试后仍然得到 ORA-04068(包的现有状态已被丢弃)
Posted
技术标签:
【中文标题】当我使用异常处理程序时,在第二次尝试后仍然得到 ORA-04068(包的现有状态已被丢弃)【英文标题】:Still getting ORA-04068 (existing state of packages has been discarded) after second try WHEN I use exception handler 【发布时间】:2017-02-10 09:38:10 【问题描述】:我有以下测试设置:
create or replace PACKAGE pkg_state
AS
FUNCTION get_variable RETURN VARCHAR2;
END pkg_state;
/
create or replace PACKAGE BODY pkg_state
AS
g_pkg_variable NUMBER(10) := 2; --testa
FUNCTION get_variable
RETURN VARCHAR2
AS
BEGIN
RETURN 'FALSE ';
END get_variable;
END pkg_state;
/
这里是测试调用:
set serveroutput on;
DECLARE
v_ReturnValue VARCHAR2(500);
BEGIN
v_ReturnValue := PKG_STATE.get_variable();
DBMS_OUTPUT.PUT_LINE('v_ReturnValue = ' || v_ReturnValue);
exception when others then
DBMS_OUTPUT.PUT_LINE('ERROR');
--raise;
END;
如果我运行它并在另一个会话中更改包,我将收到错误 ORA-04068 -> 预期。
但是如果我再次运行它(不再次更改包)它会再次失败(以及之后的每次尝试)!
如果我重新引发错误(删除“raise;”的 cmets),一切都会按预期工作:第一次错误;第二次成功了。
我认为它在第二次尝试时总会起作用。当我“吞下”错误时,为什么不呢?永远不要阅读有关此特定问题的信息。
这似乎使得无法在用户注意到任何错误的情况下捕获错误并尝试再次进行调用。 (数据库 11.2.0.4)
【问题讨论】:
为什么会发现错误?这在生产环境中永远不会发生,除非您更新软件? 我在开发过程中得到了很多,但在生产中从来没有遇到过问题。 当我们需要修补程序而我们无法调用停机时,这种情况在生产中很少发生。 1.)理论上,抓住那个 ORA 会很好,尝试再次运行你的逻辑并在它第二次失败时将其提升。但这似乎不像我的例子所示那样工作。 2.)我们有大量的旧代码和坏代码,它们“当其他人”时没有重新引发错误。 也许这有一些有用的提示:markhoxey.wordpress.com/2013/09/17/… 谢谢雷内。大多数信息我已经知道,但我对该博文的“陷阱和重试”部分感兴趣。如果您需要重新引发错误以使第二次调用正常工作,这将永远无法工作。 【参考方案1】:Oracle 在每个会话的会话内存中保存一个已编译的包实例。如果包无效,则会重新加载。
因此,需要传播此错误(引发)以清除无效包。
试图忽略包变量的无效状态是不好的做法。
【讨论】:
“忽略”太苛刻了。也许我确切地知道现在什么状态被破坏了,所以我可以捕获该异常并将用户重定向到我知道一切都有效的最后一步,而不会让用户看到错误。【参考方案2】:要处理此类问题,只需从异常块中重新运行代码即可:
DECLARE
v_ReturnValue VARCHAR2(500);
BEGIN
v_ReturnValue := PKG_STATE.get_variable();
DBMS_OUTPUT.PUT_LINE('v_ReturnValue = ' || v_ReturnValue);
exception when others then
DBMS_OUTPUT.PUT_LINE('ERROR');
v_ReturnValue := PKG_STATE.get_variable();
DBMS_OUTPUT.PUT_LINE('v_ReturnValue = ' || v_ReturnValue);
END;
【讨论】:
你试过了吗?它不起作用。这是我的问题:如果你不在异常块中重新引发它不会起作用......以上是关于当我使用异常处理程序时,在第二次尝试后仍然得到 ORA-04068(包的现有状态已被丢弃)的主要内容,如果未能解决你的问题,请参考以下文章
Swift 2:电子邮件取消按钮在第二次尝试表视图后停止工作
Firebase Firestore get() 快照在第二次查询时冻结
UIImagePickerController 在第二次取消时崩溃