在oracle中重新编译时对象何时锁定
Posted
技术标签:
【中文标题】在oracle中重新编译时对象何时锁定【英文标题】:When is the object locked while recompiling in oracle 【发布时间】:2016-09-16 14:48:20 【问题描述】:请帮助我理解这个概念。
我试图从使用以下代码的过程中编译无效包。它抛出以下错误
ORA-04021: 等待锁定对象时发生超时
for cur_rec in (select object_name, object_type
from user_objects
where object_type in ('PACKAGE', 'PROCEDURE', 'FUNCTION','PACKAGE BODY')
and status != 'VALID')
loop
begin
if cur_rec.object_type != 'PACKAGE BODY' then
execute immediate 'ALTER '||cur_rec.object_type||' usr.'||cur_rec.object_name||' COMPILE';
else
execute immediate 'ALTER PACKAGE usr.'||cur_rec.object_name||' COMPILE BODY';
dbms_output.put_line('Package recompiling finish');
end if;
end;
end loop;
我已经看到了这个网站上的所有建议。我检查了会话浏览器,但没有其他活动会话引用此包。
因此检查了 dba_dependencies 并意识到重新编译包的过程正在引用一个也在包中使用的表。但是过程中的这个表访问是在重新编译包之后进行的(换句话说,在过程和包中使用的表上触发了一个选择查询)
请帮帮我,这是错误的原因吗?你会认为改变会话。重置包而不是上面的代码会起作用还是抛出同样的错误?
【问题讨论】:
【参考方案1】:如果这是在一个过程中运行,它会不会因为当前正在运行而尝试重新编译自己并死锁?
如果你有一个程序试图删除自己,也会发生同样的死锁:
CREATE OR REPLACE PROCEDURE calc_bonus (emp_id NUMBER) AS
BEGIN
EXECUTE IMMEDIATE 'DROP PROCEDURE calc_bonus'; -- deadlock!
END;
/
【讨论】:
你好迈克尔,感谢您的回复。我正在从另一个外部过程重新编译包。据我所知,我确信在这种情况下不会出现僵局。但我的问题是:重新编译包的过程正在引用一个也在包中使用的表。但是过程中的这个表访问是在重新编译包行之后进行的(更清楚一点:在过程和包中使用的表上触发了一个选择查询)。因此会出现死锁吗? 我不这么认为,因为重新编译不会执行可能发生数据访问死锁的查询 - 它只是解析所有引用、解析和验证所有代码等。 我还应该注意,大多数人不再尝试遍历依赖树来确定要重新编译的内容 - 他们只是使用 Oracle 内置函数,例如:dbms_utility.compile_schema(your_user, false) ;重新编译架构 your_user 中的所有无效对象。 是的,你是对的,但我有一些程序有错误,所以我不希望重新编译整个架构。我在查询中使用 where 子句来限制只需要重新编译的包或过程。 其实我有一个无效的包错误。所以为了摆脱那个错误,我正在重新编译。但我仍然得到一些其他错误。可能更好的是我使用重置包并重新初始化我的包变量,或者你能建议我一些其他方法。以上是关于在oracle中重新编译时对象何时锁定的主要内容,如果未能解决你的问题,请参考以下文章