为什么执行这个块永远不会结束?

时间:2015-03-17 05:48:30

标签: oracle plsql oracle11g

假设我们有一个包PACK

package PACK is procedure DO; end PACK;

package body PACK is       
        procedure DO is begin DBMS_OUTPUT.PUT_LINE('Hello from PACK'); end;
end PACK;

为什么要执行块

begin
    PACK.do;
    execute immediate 'alter package PACK compile';
end;

永远不会结束(会话好像挂了)?但是,单独执行第一行和第二行(在不同的匿名块中)是成功的。

1 个答案:

答案 0 :(得分:4)

该软件包已被使用,这意味着它的instance仍处于活动状态。所以,除非它被杀死,否则你无法改变它的状态。

当调用过程或任何存储的函数时,该会话在该对象状态上获取锁定。除非调用者完成模块,否则锁保持活动状态。

在您的情况下,您正在尝试在调用它的同一PL / SQL块中更改包。结果为deadlock。试图动态执行你的DDL的PL/SQL块,但是当第一次调用包时,已经存在锁定了!

  

请注意,在此之后,相同的PL / SQL仍然可以调用包   动态DDL(它也可以是DROP!)。所以为了一致起见,锁定   除非整个PL / SQL已经完成,否则不会发布!

ORA-04021: timeout occurred while waiting to lock object ..

当你在单独的 PL/SQL块中调用时,锁已经被释放了。在调用DDL之前。

尝试在不同的会话中运行此SQL。

select * from v$access where object = 'PACK';