昨天看有个帖子说到的失效对象重新编译的问题,然后发现自己管的库里面貌似也经常出现莫名其妙的失效对象,于是写个存储过程建个任务计划,自动了吧--创建自动编译失效过程事务记录表
declare
  tabcnt integer := 0;
begin
  select count(*) into tabcnt from dba_tables where table_name='RECOMPILE_LOG';
  if tabcnt = 0 then
    execute immediate 'create table recompile_log(rdate date,errmsg varchar2(200))';
  end if;
end;
/--创建编译失效对象的存储过程
create or replace procedure recompile_invalid_objects  
as
  str_sql varchar2(200);  --中间用到的sql语句
  p_owner varchar2(20);   --所有者名称,即SCHEMA
  errm varchar2(200);     --中间错误信息
begin
  /*****************************************************/
  p_owner := 'owner';/***用户名*************************/
  /*****************************************************/ 
  insert into recompile_log(rdate, errmsg) values(sysdate,'time to recompile invalid objects'); 
  
  --编译失效存储过程
  for invalid_procedures in (select object_name from all_objects
    where status = 'INVALID' and object_type = 'PROCEDURE' and owner=upper(p_owner))
  loop
    str_sql := 'alter procedure ' ||invalid_procedures.object_name || ' compile';
    begin
      execute immediate str_sql;
    exception
      When Others Then
      begin
        errm := 'error by obj:'||invalid_procedures.object_name||' '||sqlerrm;
        insert into recompile_log(rdate, errmsg) values(sysdate,errm);
      end;
    end;
  end loop;
  
  --编译失效函数
  for invalid_functions in (select object_name from all_objects
    where status = 'INVALID' and object_type = 'FUNCTION' and owner=upper(p_owner))
  loop
    str_sql := 'alter function ' ||invalid_functions.object_name || ' compile';
    begin
      execute immediate str_sql;
    exception
      When Others Then
      begin
        errm := 'error by obj:'||invalid_functions.object_name||' '||sqlerrm;
        insert into recompile_log(rdate, errmsg) values(sysdate,errm);
      end;
    end;
  end loop;  --编译失效包
  for invalid_packages in (select object_name from all_objects
    where status = 'INVALID' and object_type = 'PACKAGE' and owner=upper(p_owner))
  loop
    str_sql := 'alter package ' ||invalid_packages.object_name || ' compile';
    begin
      execute immediate str_sql;
    exception
      When Others Then
      begin
        errm := 'error by obj:'||invalid_packages.object_name||' '||sqlerrm;
        insert into recompile_log(rdate, errmsg) values(sysdate,errm);
      end;
    end;
  end loop;
  
  --编译失效类型
  for invalid_types in (select object_name from all_objects
    where status = 'INVALID' and object_type = 'TYPE' and owner=upper(p_owner))
  loop
    str_sql := 'alter type ' ||invalid_types.object_name || ' compile';
    begin
      execute immediate str_sql;
    exception
      When Others Then
      begin
        errm := 'error by obj:'||invalid_types.object_name||' '||sqlerrm;
        insert into recompile_log(rdate, errmsg) values(sysdate,errm);
      end;
    end;
  end loop;  --编译失效索引
  for invalid_indexs in (select object_name from all_objects
    where status = 'INVALID' and object_type = 'INDEX' and owner=upper(p_owner))
  loop
    str_sql := 'alter index ' ||invalid_indexs.object_name || ' rebuild';
    begin
      execute immediate str_sql;
    exception
      When Others Then
      begin
        errm := 'error by obj:'||invalid_indexs.object_name||' '||sqlerrm;
        insert into recompile_log(rdate, errmsg) values(sysdate,errm);
      end;
    end;
  end loop;  --编译失效触发器
  for invalid_triggers in (select object_name from all_objects
    where status = 'INVALID' and object_type = 'TRIGGER' and owner=upper(p_owner))
  loop
    str_sql := 'alter trigger ' ||invalid_triggers.object_name || ' compile';
    begin
      execute immediate str_sql;
    exception
      When Others Then
      begin
        errm := 'error by obj:'||invalid_triggers.object_name||' '||sqlerrm;
        insert into recompile_log(rdate, errmsg) values(sysdate,errm);
      end;
    end;
  end loop;
 
end;
/--创建任务计划,每天早上8点整执行该任务,且保证此任务有且只有一个
declare 
  jobcnt integer :=0;
  job_recompile number := 0;
  str_sql varchar2(200);
begin 
  select count(*) into jobcnt from all_jobs where what = 'recompile_invalid_objects;' and broken = 'N';
  if jobcnt > 0 then
    for jobs in (select job from all_jobs where what = 'recompile_invalid_objects;' and broken = 'N')
    loop
      str_sql := 'begin dbms_job.remove('||jobs.job||'); end;';
      begin
        execute immediate str_sql;
      exception
        When Others Then null;
      end;
    end loop; 
  end if;
  --创建任务计划
  dbms_job.submit(job_recompile,'recompile_invalid_objects;',sysdate,'TRUNC(SYSDATE + 1) + 8/24');
  --启动任务计划
  dbms_job.run(job_recompile);
end;
/
有什么不足或没有考虑到的情况没,请指教。

解决方案 »

  1.   

    对于实效的存储过程或函数对象,如果代码本身没有什么错误,只是引用的对象发生了变化。
    也会失效。但并不影响调用,因为oracle在调用时会自动重新编译的,如果其它对象变化后
    导致编译有错误。这时调用时重新编译后也是错误并处于失效状态,所以调用会出错。只不过如果在并发状态下调用失效对象,可能会存在资源争用。所以编写一个自动编译
    的功能也是不错的。
      

  2.   


    呃,没深入看过,我想问下oracle自动编译后应该是查询失效对象查不到了吧……
    但是应该调用了很多次,但是查找失效对象还是能找到,手动重新编译也不报错啊……
      

  3.   

    收藏了先~
    失效的存储过程,执行的时候确实可以重新编译,但是如果想调试,debug就会进不去!
      

  4.   

    楼主的想法是好的,但过程太过复杂,1.oracle提供了自动编译的接口
    dbms_utility.compile_schema(user,false);
    调用这个过程就会编译所有失效的过程、函数、触发器、包2.自动失效的对象,一般会在下次调用的时候,被重新编译通过,所以不需要人工干预3.自动编译所有的过程还可以,但我觉得重建索引就需要慎重考虑了,因为在索引重建的时候,其是不会被使用的,若索引比较大,持续时间比较长,你前端的业务就比较危险了
    我个人认为,只要建立一个查看失效对象的机制就可以了,至于处理方法就没必要自动了
    不过还是比价欣赏LZ的动手能力,
      

  5.   

    失效存储过程?一般失效的都是错误的吧,除非你是在生产库上座改动的,一般需要重新编译才能生效我都是用PL/SQL DEV里的有个检查失效对象,然后重编译
      

  6.   

    1.我也高明不到哪地方去
    2.存储过程一般情况下只在被引用的对象上做了ddl操作,才会失效,你们的系统中为什么会自动出现失效对象,我也不太清楚,是不是存在自动增加或删除分区表、自动建索引等ddl操作
    3.只要索引失效,查询的时候就不会使用索引,一般情况下,索引都不会失效
    我所说的机制其实和你理解的差不多,就是只要把失效的索引找出来就可以了