在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中重新编译时对象何时锁定的主要内容,如果未能解决你的问题,请参考以下文章

重新编译PLSQL中无效对象或指定对象

如何在 Oracle 10g DB 中重新编译 SYS 用户中的无效 Java 类对象?

重新编译 oracle 包时更新的缓存是啥?

转://oracle 重新编译用户无效对象

在重新编译oracle包时,哪些缓存会更新?

DataGrip - 编译无效对象 (Oracle)