fchdb

1、数据库对象失效的原因很多,下面大致归纳了一些常见的原因
(1)当被引用对象的结构变更时,都会使得相关的依赖对象转变为INVALID状态。数据库中的对象(存储过程,函数,包,视图,触发器),它们往往需要直接或者间接的引用其它对象,对象的依赖包括直接和间接二种,其中直接依赖是指存储对象直接依赖于被引用对象,而间接依赖是指对象间接依赖于被引用对象

要查看被引用的对象,可以通过下面SQL查看

select * from dba_dependencies where name=\'&objectname\';

举个简单例子,视图V_TEST引用了表TEST,TEST表修改了表结构时,会导致视图V_TEST变为无效对象。

CREATE TABLE TEST ( ID NUMBER(10));
CREATE VIEW V_TEST AS SELECT * FROM TEST;
ALTER TABLE TEST ADD NAME VARCHAR(12);
SELECT OBJECT_NAME, STATUS FROM DBA_OBJECTS WHERE OBJECT_NAME=\'V_TEST\';

其实不管视图,像存储过程,函数、包等,如果代码本身没有什么错误,只是引用的对象发生了变化。也会失效。但并不影响调用,因为ORACLE在调用时会自动重新编译的,如果其它对象变化后导致编译有错误。这时调用时重新编译后也是错误并处于失效状态,所以调用会出错。

(2)发布SQL脚本时(包、存储过程、函数等),没有充分测试,编译时出错,这时对象变为无效。

(3) 数据库升级、迁移时,出现大量无效对象(本质原因,个人臆测归结为原因1)。
(4) 诸如此类各种情况:例如,Oracle 会自动维护分区索引,对于全局索引,如果在对分区表操作时,没有指定update index,则会导致全局索引失效,需要重建。

2、编译失效对象的方法

 ---统计失效的对象数:

select owner, object_type, status, count(*)
from dba_objects
where status=\'INVALID\'
group by owner, object_type, status
order by owner, object_type;

---查看具体失效对象

col owner for a20;
col object_name for a32;
col object_type for a16
col status for a8
select owner, object_name, object_type, status
from dba_objects
where status=\'INVALID\'
order by 1, 2,3;

---编译无效对象方法一

set heading off; 
set feedback off; 
set echo off; 
Set lines 999; 
 
spool run_invalid.sql 
 
select 
\'ALTER \' || OBJECT_TYPE || \' \' || 
OWNER || \'.\' || OBJECT_NAME || \' COMPILE;\' 
from 
dba_objects 
where 
status = \'INVALID\' 
and 
object_type in (\'PACKAGE\',\'FUNCTION\',\'PROCEDURE\',\'TRIGGER\',\'JAVA SOURCE\',\'JAVA CLASS\',\'\') 
; 
spool off; 
set heading on; 
set feedback on; 
set echo on; 
 
@run_invalid.sql  

---编译无效对象方法二:

dbms_utility.compile_schema(\'feng\',false); 

compile_all

If TRUE, will compile everything within the schema regardless of whether it is VALID

If FALSE, will compile only INVALID objects

---编译无效对象方法三

执行@$ORACLE_HOME/rdbms/admin/utlrp.sql脚本编译数据库失效对象。

许多情况下,由于数据库的升级或迁移,会导致数据库中的对象失效。由于对象之间可能存在复杂的倚赖关系,所以手工编译通常无法顺利通过。通常我们会在Oracle的升级指导中看到这个脚本,Oracle强烈推荐
在migration
/upgrade/downgrade之后,通过运行此脚本编译失效对象。但是注意,Oracle提醒,此脚本需要用SQLPLUS以SYSDBA身份运行,并且当时数据库中最好不要有活动事物或DDL操作,
否则极容易导致死锁的出现。
另外,utlrp.sql 里面其实调用了$ORACLE_HOME/rdbms/admin/utlrcmp.sql来编译失效对象。

---oracle失效对象定期自动编译脚本

--1、创建自动编译失效过程事务记录表
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;
/
 
--2、创建编译失效对象的存储过程
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;
/
 
--3、创建任务计划,每天早上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;
 

 

分类:

技术点:

相关文章:

  • 2021-10-07
  • 2021-10-11
  • 2021-09-27
  • 2021-10-11
  • 2022-12-23
猜你喜欢
  • 2022-12-23
  • 2021-10-26
  • 2022-01-31
  • 2021-11-12
  • 2022-01-01
  • 2021-06-05
  • 2022-12-23
相关资源
相似解决方案