smon_scn_time表和索引交叉引用失效导致服务器性下降,CPU使用率100%,简单记录一下处理过程。
从服务器负载来看,负载非常小,session也在比较低的范围内,如下图所示
从TOP 5上看,也没有特殊的等待事件,如下图所示
从SQL ordered by Elapsed Time、SQL ordered by CUP Time等几个模块来看,同样一个表smon_scn_time的删除操作有明显异常,如下图所示
当时以为是业务上的以一表,用普通用户连数据库以后查看提示不存在,再仔细一看表名,像是sys下面的一个表,当时自己也不知道这个表做什么的,网上查了一下,smon_scn_time是由smon进程维护的,记录scn和time之间对应关系的一种表,此表是聚簇表并且是循环写,意思是边写边删除,它是由SMON进程每隔5分钟或10分钟生成一次SCN和TIME之间的映射记录,具体多少分钟要看业务繁忙程度,并更新到SMON_SCN_TIME表中,同时删除五天以前的记录,该表的维护周期是5天最多能保存144000条记录,并且该表和索引交叉引用失效会导致服务器性能下降(事后查资料才知道),而我遇到的情况更狠,直接CPU使用率100%了,数据库版本是10.2.0.4的数据库,因为是十一期间,其它同类型数据库该表的记录在1500-1700条记录之间,而CPU使用率100%的数据库记录在87146条,明显多出很多,并且该表的删除操作从AWR上看已经严重不正常了。
当时的处理方法是:(此方法并没有解决根本问题)
1> 查看索引状态
select index_name,status,last_analyzed from dba_indexes where table_name='SMON_SCN_TIME';
状态是VALID 上次分析时间是2013-05-07小半年了没分析了
2> 查看表的上次统计信息收集时间
select last_analyzed from dba_tables where owner='SYS' and table_name='SMON_SCN_TIME'
结果也是2013-05-07
当时果断以为是统计信息过旧造成的执行效率低下,进行了如下处理
3> 重创索引
alter index SMON_SCN_TIME_SCN_IDX rebuild online;
alter index SMON_SCN_TIME_SCN_IDX rebuild online;
3> begin
dbms_stats.gather_table_stats(ownname => 'SYS',
tabname => 'SMON_SCN_TIME',
cascade => TRUE);
end;
处理完以后,CPU并没有很快降下来,停掉应用,大概过了十几分钟以后,CPU才逐步恢复到正常值,后来总感觉处理方法那里出了问题,没真正搞明白是怎么回事,同时又看了服务器上的AWR报告,delete from smon_scn_time这个操作还是有异常,又查询了相关资料,此问题的根本原因在于索引和表的交叉引用失效导致的,并且rebuild index并不能解决问题,正确的方法方法是:
1> 查看表和索引的状态,此处省略,和上面一样,要确保索引状态是VALID状态
2> 判断是否是因为表和索引交叉引用失效
analyze table smon_scn_time validate structure cascade online;
报错很明显,表和索引交叉引用失效,失效后会对表smon_scn_time加一个排它锁,并且不释放,导致删除性能下除,体现在AWR报告中,这是原因,下面进行验证是否有排它锁长期存在
3> 先找查对像ID
select object_id from dba_objects where object_name = 'SMON_SCN_TIME';
576
4> 查看是否存在锁,以及锁的模式
select object_id,locked_mode from v$locked_object where object_id = '576';
576 3 --排它锁,并且多次刷新一直存在,证明我们前期的猜测
5> 表和交叉索引失效后,rebuilt索引并不能解决问题,只能drop index然后重新,删除前需要备份创建
DDL以防万一(切记)
--查找索引
select * from dba_indexes where table_name='SMON_SCN_TIME';
--备份索引创建DDL
select dbms_metadata.get_ddl('INDEX','SMON_SCN_TIME_TIM_IDX','SYS') from dual;
--备份索引创建DDL
select dbms_metadata.get_ddl('INDEX','SMON_SCN_TIME_SCN_IDX','SYS') FROM dual;
6> 删除索引并重新创建
--删除索引
drop index sys.SMON_SCN_TIME_TIM_IDX;
drop index sys.SMON_SCN_TIME_SCN_IDX;
注意,删除时会提示ORA-00054: resource busy and acquire with NOWAIT specified是
因为和索引交叉引用失效后,删除语句找时间执行不能正常结束,此时只能不停的删除尝试,因为此
处无法使用kill session方式进行处理,多试几次等待删除SQL执行完以后就可以正常删除索。
--重新创建索引
create unique index "sys"."smon_scn_time_tim_idx" on "sys"."smon_scn_time" ("time_mp");
create unique index "sys"."smon_scn_time_scn_idx" on "sys"."smon_scn_time" ("scn");
7> 重新验证表和索引交叉引用是否正常
analyze table smon_scn_time validate structure cascade online;
--注意要用online否则将导致DML无法进行
--此时无报错,问题解决
8> 查看锁已经消失
select object_id,locked_mode from v$locked_object where object_id = '576';
--此处无数据
9>查询并处理失效对像
selec