为什么这个块的执行永远不会结束?
Why execution of this block never ends?
假设我们有一个包 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;
永远不会结束(会话似乎挂起)?但是,分别执行第一行和第二行(在不同的匿名块中)是成功的。
该包已被使用,这意味着它的 instance
仍然有效。所以,除非它被杀死,否则你不能改变它的状态。
调用过程或任何存储函数时,该会话将获取对该对象状态的锁定。除非调用者完成模块,否则锁将保持活动状态。
在您的情况下,您正试图在调用它的同一个 PL/SQL 块中更改包。结果为 deadlock
。 PL/SQL
块试图动态执行您的 DDL,但在首次调用包时已经锁定!
Please note that same PL/SQL can still call the package after this
dynamic DDL (It can be DROP
too!). So for consistency sake, the lock
is not released unless the entire PL/SQL is been completed!
ORA-04021: timeout occurred while waiting to lock object ..
Where-as,当您调用 separate PL/SQL
块时,锁已经被释放。在调用 DDL 之前。
正在另一个会话中尝试 运行 这个 SQL。
select * from v$access where object = 'PACK';
假设我们有一个包 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;
永远不会结束(会话似乎挂起)?但是,分别执行第一行和第二行(在不同的匿名块中)是成功的。
该包已被使用,这意味着它的 instance
仍然有效。所以,除非它被杀死,否则你不能改变它的状态。
调用过程或任何存储函数时,该会话将获取对该对象状态的锁定。除非调用者完成模块,否则锁将保持活动状态。
在您的情况下,您正试图在调用它的同一个 PL/SQL 块中更改包。结果为 deadlock
。 PL/SQL
块试图动态执行您的 DDL,但在首次调用包时已经锁定!
Please note that same PL/SQL can still call the package after this dynamic DDL (It can be
DROP
too!). So for consistency sake, the lock is not released unless the entire PL/SQL is been completed!
ORA-04021: timeout occurred while waiting to lock object ..
Where-as,当您调用 separate PL/SQL
块时,锁已经被释放。在调用 DDL 之前。
正在另一个会话中尝试 运行 这个 SQL。
select * from v$access where object = 'PACK';