一、无效对象的识别和编译
1、识别无效对象
col object_name for a30
select object_name, object_type from dba_objects where owner = 'CMES' and status='INVALID';
2、编译单个无效对象
语法:alter 对象类型 对象名称 compile;
如重新编译某个存储过程,编译不能通过时,可用SQL*Plus命令show errors查看原因,但是视图不支持show errors:
alter procedure cmes.m085i_chk_lot compile;
警告: 更改的过程带有编译错误。
show errors;
PROCEDURE CMES.M085I_CHK_LOT 出现错误:
LINE/COL ERROR
-------- -----------------------------------------------------------------
27/7 PLS-00103: 出现符号 "="在需要下列之一时:
:= . ( @ % ;
符号 ":=在 "=" 继续之前已插入。
可以使用视图dba_dependencies查看对象间的依赖关系,便于分析编译错误的原因,如:
col owner for a10
col name for a20
col referenced_owner for a20
col referenced_name for a20
col referenced_link_name for a20
select * from dba_dependencies where owner = 'CMES' and name='FS_GET_CHANNEL' and referenced_owner != 'SYS';
OWNER NAME TYPE REFERENCED_OWNER REFERENCED_NAME REFERENCED_TYPE REFERENCED_LINK_NAME DEPENDENCY_TYPE
---------- -------------------- ------------------ -------------------- -------------------- ------------------ -------------------- ---------------
CMES FS_GET_CHANNEL PROCEDURE CMES FS_CHANNEL_T TABLE HARD
CMES FS_GET_CHANNEL PROCEDURE CMES FS_CHK_CONDITION PROCEDURE HARD
CMES FS_GET_CHANNEL PROCEDURE CMES FS_CONDITION_T TABLE HARD
CMES FS_GET_CHANNEL PROCEDURE CMES C_SILO_T TABLE HARD
CMES FS_GET_CHANNEL PROCEDURE RMES R_BOLT_RECORD_T TABLE HARD
CMES FS_GET_CHANNEL PROCEDURE RMES R_WIP_BOL_T TABLE HARD
CMES FS_GET_CHANNEL PROCEDURE CMES C_BOLT_T TABLE HARD
3、通过Oracle自带的脚本可以编译全部无效对象
用系统自带的脚本可以执行对全部无效对象的编译,注意该脚本必须以SYSDBA身份运行:
@?\rdbms\admin\utlrp
4、通过构建SQL编译无效对象
批量编译无效对象的一种方法就是利用以下SQL查询批量生成编译语句,然后提取执行。该方法的好处是可以比较灵活的选择对象来执行,并且无需以SYSDBA身份登录:
select 'alter procedure ' || object_name || ' compile;' from dba_objects where owner = 'CMES' and status='INVALID';
5、通过以下存储过程编译无效对象
如果提取utlrp的脚本,可以重新组织成一个用于编译所有无效对象的存储过程
create or replace procedure recompile as
-- 编译无效对象
type tab_char is table of varchar2(32767) index by binary_integer;
commands tab_char;
table_exists number;
begin
utl_recomp.recomp_parallel(0);
select count(*)
into table_exists
from dba_objects
where owner = 'SYS'
and object_name = 'UTLIRP_ENABLED_FUNC_INDEXES'
and object_type = 'TABLE';
if (table_exists > 0) then
execute immediate q'+
select 'alter index "' || u.name || '"."' || o.name || '" enable'
from utlirp_enabled_func_indexes e, ind$ i, obj$ o, user$ u
where e.obj# = i.obj# and i.obj# = o.obj# and o.owner# = u.user#
and bitand(i.flags, 1024) != 0+' bulk
collect
into commands;
if (commands.count() > 0) then
for i in 1 .. commands.count() loop
execute immediate commands(i);
end loop;
end if;
execute immediate 'drop table utlirp_enabled_func_indexes';
end if;
dbms_registry_sys.validate_components;
end;
二、不可用索引及其修复
如果某个存储过程对象变为无效,DBA可以不执行任何操作,首次访问该对象时,Oracle会尝试进行重新编译。但如果索引变得不可用,则必须显示的修复它。
在10g以前的版本中,如果会话试图使用不可用的索引,那么会立即返回一条错误消息,同时语句执行失败。但10g开始更改了这种方式,如果索引不可用,那么语句会重走不需要该索引的执行计划,执行总会成功,虽然性能可能会显著下降。
有一个实例参数控制该行为:skip_unusable_indexes,默认为true,表示即便索引不可用,也可以执行语句。这是一个动态参数,如想实现旧版本中不可用索引导致返回错误消息的功能,则可将其修改为false。
即便skip_unusable_indexes为true,对于通过索引实施约束的情况是一个例外,如主键约束,需要建立索引,如果主键上的索引变得不可用,那么会对DML命令锁定表,此时无法进行DML操作。
1、查询不可用索引
select table_name, index_name, index_type, tablespace_name, uniqueness from dba_indexes where owner = 'CMES' and status = 'UNUSABLE';
2、修复不可用索引
如果rowid指针不再正确,则索引将标记为不可用。为了修复不可用索引,可以使用以下命令重建索引:
alter index 索引名 rebuild [tablespace 表空间名] [online] [nologging];
tablespace:默认索引在当前表空间内重建,也可以指定重建在其它表空间上。
online:默认重建索引过程会对DML命令锁定表,若使用该参数则不会影响DML的操作。
nologging:指示Oracle不为索引重建操作生成重做,这样重建速度将加快,但也意味着应当对包含指定索引的表空间进行备份。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/28974745/viewspace-2138333/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/28974745/viewspace-2138333/