今天在执行EBS工作流的时候,遇到了一个及其古怪的问题,下面我把我遇到的问题及其解决问题的整个过程分享给大家。
首先我提交了工作流wf_a, 提交完成后在前台查看工作流,工作流状态为active(这点对于解决问题很重要),因为遇到问题不能继续向下进行。
第二步,修改后台对应的程序package: pkg_b.func_c.
第三步,重新提交工作流wf_a,这时遇到了如下错误:
ORA-04068: existing state of packages has been discarded
ORA-04061: existing state of package "pkg_b.func_c" has been invalidated
ORA-04065: not executed, altered or dropped package "pkg_b.func_c"
ORA-06508: PL/SQL: could not find program unit being called
这个错误太奇怪了,我的程序明明好好的,为什么会提示这种错误呢?我想那就baidu吧,那就google 吧, 那就metalink吧,总之是查了很久感觉总和我遇到的问题对不上号,就在快要放弃的时候,终于看见了一片文章《OraclePLSQL之子程序和包》里面有这么一段描述:
包运行状态的相关:
除了在存储对象之间的存在着相关外,包状态和匿名块之间也有相关特性。例如,请看下面的包:
节选自在线代码anonymousDependencies.sql
包SimplePkg包含了一个包全局量 v_GlobalVar.假设我们从一个数据库会话创建包 SimplePkg.接着,在第二个会话中,我们使用下面的块来调用 SimplePkg.UpdateVar:
现在返回第一个会话,我们运行创建脚本再次创建包 SimplePkg。最后,我们在第二个会话中提交同样的匿名块。下面是得到的输出信息:
上面的程序发生了什么问题?图 5 - 1 3是上述情况的相关图示。匿名块依赖于包 SimplePkg。这种相关是编译时的依赖性,也就是在匿名块首次编译时就确定的相关关系。然而,除此之外,由于每个会话都有其自己包变量的复本,所以运行时包变量之间也存在着依赖关系。因此,当重编SimplePkg时,运行时相关就紧随其后,引发了错误ORA-04068并作废了该块。
运行时相关仅存在于包状态之上,它包括包中的变量和游标声明。如果包没有全局变量的话,则匿名块的第二次运行将会成功。
匿名块依赖于SimplePky,并包括v_Globa Var的实例
图5-13 包的全局相关图示
到这里我终于明白了,有种顿悟的感觉。也就是说在一个会话中调用程序包package时,会生成package中全局变量的副本,如果在另一个会话中对此package进行编译就会使前一个会话中的副本失效,故而产生错误。
因此,我查看自己的程序,发现确实存在着全局变量。对照这种说法,那么就是我之前提交的工作流wf_a(相当于会话)存在着pkg_b中全局变量的副本,并且此工作流是active状态,所以我在编译pkg_b之后,就触发了ORA-04068的错误。
那么既然知道了错误产生的原因,解决起来就容易了。
我将之前提交的工作流只要是活动的就全部取消,这样会将其占用的会话释放掉,因此也就不会存在pkg_b的在别的会话当中的副本。然后重新提交工作流wf_a,果然不出所料,工作流顺利通过。