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

3 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;
Run Code Online (Sandbox Code Playgroud)

为什么执行块

begin
    PACK.do;
    execute immediate 'alter package PACK compile';
end;
Run Code Online (Sandbox Code Playgroud)

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

Mah*_*kar 5

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

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

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

请注意,相同的 PL/SQL 仍然可以在此动态 DDL 之后调用包(它也可以DROP!)。所以为了一致性,除非整个 PL/SQL 完成,否则锁不会被释放!

ORA-04021: timeout occurred while waiting to lock object ..
Run Code Online (Sandbox Code Playgroud)

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

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

select * from v$access where object = 'PACK';
Run Code Online (Sandbox Code Playgroud)