oracle 对象失效(objects INVALID)
在日常数据库维护过程中,我们会发现数据库中一些对象(包Package、存储过程Procedure、函数Function、视图View、同义词…)会失效,呈现无效状态(INVALID)。
有时候需要定期检查数据库中存在哪些失效对象,对于存在异常的对象需要重新编译,有些自动失效的对象,一般会在下次调用的时候,会被重新编译,所以这些不需要人工干预。
那么为什么对象突然会失效呢?又如何快速、高效的编译失效对象呢?哪些失效的对象不需要我们去重新编译呢?
1 数据库对象失效原因
数据库对象失效的原因很多,下面大致归纳了一些常见的原因(有些漏掉的,希望大家补充):
1: 当被引用对象的结构变更时,都会使得相关的依赖对象转变为INVALID状态。(可创建view,更改表结构验证)
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;
3 Oracle中编译无效的对象常用方法
3.1 ALTER *** COMPLIE语句
手工进行编译,这个适用于少数、个别对象失效
alter package .<package_name> compile;
alter package .<package_name> compile body;
alter view .<view_name> compile;
alter trigger <schema).<trigger_name> compile;
3.2 sql脚本
@$ORACLE_HOME/rdbms/admin/utlrp.编译数据库失效对象。
许多情况下,由于数据库的升级或迁移,会导致数据库中的对象失效。由于对象之间可能存在复杂的倚赖关系,所以手工编译通常无法顺利通过。
通常我们会在Oracle的升级指导中看到这个脚本,Oracle强烈推荐在migration/upgrade/downgrade之后,通过运行此脚本编译失效对象。
但是注意,Oracle提醒,此脚本需要用SQLPLUS以SYSDBA身份运行,并且当时数据库中最好不要有活动事物或DDL操作,否则极容易导致死锁的出现(这是很容易理解的)。
3.3 自动编译的接口
ORACLE提供了自动编译的接口dbms_utility.compile_schema(user,false); 调用这个过程就会编译所有失效的过程、函数、触发器、包
exec dbms_utility.compile_schema( ‘SCOTT’ )
3.4 一些网友书写的编译失效对象
SQL 1: 编译失效对象
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
SQL 2:在上面的方法中,只能知道某某编译失败,不清楚失败原因,可以用PL/SQL实现更详细的错误信息
DECLARE
v_objname user_objects.object_name%TYPE;
v_objtype user_objects.object_type%TYPE;
CURSOR cur IS
SELECT object_name,object_type
FROM USER_OBJECTS
WHERE status = 'INVALID'
AND object_type IN ('FUNCTION','JAVA SOURCE','JAVA CLASS','PROCEDURE','PACKAGE','TRIGGER');
BEGIN
OPEN cur;
LOOP
FETCH cur into v_objname, v_objtype;
EXIT WHEN cur%NOTFOUND;
BEGIN
EXECUTE Immediate 'alter ' || v_objtype || ' ' || v_objname||' Compile';
dbms_output.put_line('编译' || v_objtype || ' ' || v_objname || '()成功');
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('编译' || v_objtype ||' ' || v_objname || '()失败.' || SQLERRM);
END;
END LOOP;
CLOSE cur;
END;