`
sony-soft
  • 浏览: 1028882 次
文章分类
社区版块
存档分类
最新评论

ORA-01555错误详解

 
阅读更多

ORA-01555错误详解

ORA-01555(快照过旧)问题让很多人感到十分头痛。最近我们的生产系统上也报出了ORA-01555错误。就结合这次案例将ORA-1555问题作个案例分析,并浅析产生原因和各种解决办法。

如果要了解1555错误产生的原因,就需要知道ORACLE的两个特性:一致性读(Consistent Get)和延迟块清除(Delayed Block Cleanout)。此外,还要知道关于回滚段的一些配置参数。

相关参数

先看下Oracle中关于UNDO有哪些配置参数:

SQL> show parameter undo

NAME TYPE VALUE
--------------------- -------------------- -----------------------
undo_management string MANUAL
undo_retention integer 900
undo_suppress_errors boolean FALSE
undo_tablespace string UNDOTBS1

undo_management

回滚段的管理方式。值可以为MANUAL/AUTO9i中默认是MANUAL10g中默认是AUTO

9i后,回滚段就以表空间的形式管理,并且支持系统自动管理回滚段。一个回滚表空间上可以创建多个回滚段,一个数据库可以创建多个回滚表空间。但是,一个实例(Instance)只能使用一个回滚表空间。

如果undo_management设置为MANUAL,就是手动创建回滚段:

SQL> create rollback segment undo1 tablespace UNDOTBS1;

如果设置为AUTOOracle就自动管理回滚段的创建,而手工创建就会失败。

undo_retention

这个参数设置回滚段中的被提交或回滚的数据强制保留时间,单位是秒。请注意,这个参数和1555错误有非常大的关系。但是,需要提醒的是,并不是回滚段中的数据超过这个时间以后就会被清除掉,而是等到后面事务产生的回滚数据覆盖掉“超期”数据。所以这就是为什么我们往往看到系统的回滚表空间占有率始终是100%的原因了。

undo_suppress_errors

是否报与回滚段有关的错误。如果为FALSE,就不会产生与回滚段有关的错误。但是,请注意,并不是不会发生回滚段错误,而只是屏蔽错误信息,错误发生了就会存在滴。在10g中,这个参数是隐含参数。

undo_tablespace

为每个实例制定的唯一当前使用的回滚段表空间。

一致性读(ConsistentGet)

一致性读(Consistent Get)可以说是产生1555错误的主要原因。但它的确是Oracle一个非常优秀的特性。既然这个特性会产生这么烦人的错误,我为什么还说它是ORACLE十分优秀的特性呢?下面就先了解一下这个特性:

并发事务和脏读

需要先了解一下这一特性的产生的背景原因。看下以下这个例子。在一个银行系统中(一般涉及到钱的问题对并发事务要求是最严格的^_^),会计正在统计当月某地区的个人存款总额,她的这个操作,在后台肯定要产生一条SQL语句,对这一地区的所有用户的存款额作SUM(),我们假设这一操作产生的语句为A,时间点是T1。由于存款用户非常多,再加上会有一些对其他表的JOIN条件,语句A的执行时间可能比较长。这时,在A的执行过程中,A已经统计了账户X的钱,但还没有统计到账户Y的钱的时候,正好有一个客户通过ATM机从账户X中转250元钱到帐户Y,他的操作也产生了一条语句B,对存款表进行更新。开始时间点是T2,结束时间是T3。因为只更新两条记录,这个过程非常短。A结束时的时间点是T4。让我们看下过程图,看看会产生什么结果:

从图中,我们可以看到,T2时刻A已经统计过帐户X中的钱,但在这时BX中转了250元到帐户Y中,在B结束的时刻T3A还没有统计到Y,但Y已经多出了250元了,所以到T4,统计结束时,A实际上多统计出250元。这就是并发事务中的“脏读(dirtyread)”问题。

在标准SQL中,为了防止并发事务中产生脏读,就需要通过加锁来控制。这样就会带来死锁、阻塞的问题,即时是粒度最小的行级锁,也无法避免这些问题。再看下上面这个例子。为了防止脏读,A在开始时就需要对表加锁,防止其他事务更新表。这样,B就会被阻塞,假如A事务要执行1个小时,B可能最长就要被阻塞1个小时(如果你是那个倒霉的客户,可能早就***骂出来了)。再看下图,

从图中,可以看到,B开始时,存款表被加锁了,所以BA阻塞,只有等A释放锁以后,B才能更新表。所以B被阻塞了很长时间。在大量并发事务系统中,可能会使整个系统慢得不可想象。

一致性读

为了解决这一矛盾。Oracle充分利用的回归段,通过会滚段进行一致性读取,即避免了脏读,又大大减少了系统的阻塞、死锁问题。下面就看下Oracle是如何实现一致性读的:

Oracle更新数据块(Data Block Oracle中最小的存储单位)时,会在两个地方记录下这一更新动作。一个是重做段(Redo Segment),是用于数据库恢复(Recover)用的。一个是回滚段(UNDO Segment),而回滚段是用于事务回滚(Rollback)的(我们只关心回滚段了)。并在数据块头部标示出来是否有修改数据。一个语句在读取数据快时,如果发现这个数据块是在它读取的过程中被修改的(即开始执行读操作时并没有被修改),就不直接从数据块上读取数据,而是从相应的回滚段条目中读取数据。这就保证了最终结果应该是读操作开始时的那一时刻的快照(snapshot),而不会受到读期间其他事务的影响。这就是Oracle的一致性读,也可以叫做多版本(Multi-Versioning)。

以上面的例子为例,A在读取到Y帐户时,发现这条记录已经被修改了,于是就从回滚段读取保留的回滚数据,最终就能正确得到T1时刻的正确存款总额了。看下图:

从图上看出,A即能得出正确的数据,又保证B不会被阻塞。

延迟块清除

再介绍一下另外一个可能产生1555错误的概念——延迟块清除(Delayed Block Cleanout)。但个人认为,如果不从字面意思上翻译,应该把它叫做延迟锁清除更加让人容易理解一些。

我们知道,当Oracle更新数据块时,会在回滚段(UNDO Segment)记录下这一更新动作。并且产生一个Cleanout SCN,在回滚段中,会产生对应的Transaction ID以及相应的数据记录镜像。并在对应的数据记录上,产生锁标志。在事务提交(commit)前,会在数据块的头部记录下这个Cleanout SCN(Csc)号、Undo BlockAddress(Uba)和Transaction ID(Xid);并且在在对应InterestedTransaction List(Itl)中设置锁标志,记录这个事务在这数据块中产生的锁的数目;同时在对应修改的数据记录上打上行级锁标志,并映射到对应的Itl去。当提交时,并不会一一清除掉所有锁标志,而是给对应的Itl打上相应标志,告诉后面访问该数据块的事务,相应的事务已经提交。这就叫做快速提交(Fast Commit)。而后面访问该数据块的的事务就先检查锁标志和对应的事务状态,如果发现前面的事务没有提交,并且要访问的数据记录被锁住了,就被阻塞;否则就清除相应的锁标志,并提交自己的锁标志,再重复以上动作。这就事延迟块清除。

而如果前面的事务在提交之前buffer cache中的脏数据已经被DBwn进程写回,那么Itl中的事务标志就不会被更新,并且数据块的Itl列表也不会记录下事务的Commit SCN。后面的事务或查询语句访问该数据块时,为了检测是否需要进行一致性读(如果数据块的Itl中记录的提交事务的Commit SCN大于当前访问该数据块的SCN,则需要进行一致性读),就需要通过Undo Block AddressTransaction ID到回滚段的事务信息表中去检查前面事务的状态和它的Commit SCN,确定是否做一致性读,最后将前面事务在该数据块上的标志做一次Cleanout

下面就举一个例子:

创建测试表:

SQL> create table t_multiver (a number, b number);

Table created.

插入测试数据,这时,实际上已经产生了一个对数据块修改的事务:

SQL> insert into t_multiver values (1,1);

1 row created.

SQL> insert into t_multiver values (2,2);

1 row created.

SQL> insert into t_multiver values (3,3);

1 row created.

SQL>
SQL> commit;

Commit complete.

修改记录,并且在commit之前将脏数据写回:

SQL> conn demo/demo
Connected.
SQL> update t_multiver set b=115 where a=1;

1 row updated.

SQL> alter system flush buffer_cache;

System altered.

SQL> commit;

Commit complete.

Dump出数据块:

SQL> alter system dump datafile 5 block 50959;

System altered.

看看Dump出来的内容:

Block header dump: 0x0140c70f
 Object id on Block? Y
 seg/obj: 0xe46c csc: 0x00.a482a47c itc: 2 flg: E typ: 1 - DATA
 brn: 0 bdba: 0x140c709 ver: 0x01 opc: 0
 inc: 0 exflg: 0

Itl Xid Uba Flag Lck Scn/Fsc
0x01 0x0012.02d.0000049c 0x02c00080.0192.0f ---- 1 fsc 0x0000.00000000
0x02 0x000f.01b.00000533 0x02c00054.01bb.0f C--- 0 scn 0x0000.a482a3c3

data_block_dump,data header at 0x7505664
===============
tsiz: 0x1f98
hsiz: 0x18
pbl: 0x07505664
bdba: 0x0140c70f
 76543210
flag=--------
ntab=1
nrow=3
frre=-1
fsbo=0x18
fseo=0x1f4a
avsp=0x1f62
tosp=0x1f62
0xe:pti[0] nrow=3 offs=0
0x12:pri[0] offs=0x1f5e
0x14:pri[1] offs=0x1f4a
0x16:pri[2] offs=0x1f54
block_row_dump:
tab 0, row 0, @0x1f5e
tl: 10 fb: --H-FL-- lb: 0x1 cc: 2
col 0: [ 2] c1 02
col 1: [ 3] c2 02 10
tab 0, row 1, @0x1f4a
tl: 10 fb: --H-FL-- lb: 0x0 cc: 2
col 0: [ 2] c1 03
col 1: [ 3] c2 03 17
tab 0, row 2, @0x1f54
tl: 10 fb: --H-FL-- lb: 0x0 cc: 2
col 0: [ 2] c1 04
col 1: [ 3] c2 03 17
end_of_block_dump
End dump data blocks tsn: 5 file#: 5 minblk 50959 maxblk 50959

其余的内容在我们讨论的这个问题中不需要太关心,主要注意红色黑体部分和InterestedTransaction Slot (ITS)部分。

CSC:Cleanout SCN,它是在我们的insert操作事务中产生的。

Flag事务标志位。由于我们在提交之前将buffer cache手动flush了,所以标志位为空。请注意到,我们这在commit之前DBwn已经写回了脏数据,标志为空。各个标志的含义分别是:

C--- = transaction has beencommitted and locks cleaned out

-B-- = this undo recordcontains the undo for this ITL entry

--U- = transaction committed(maybe long ago); SCN is an upper bound
---T = transaction was still active at block cleanout SCN

可以看到,目前事务标志是U,即事务已经提交,但是相应的锁并没有清除。所以,看到后面的Lck位(行级锁数目)为1(因为我们修改了1条记录)。

再看每条记录中的行级锁对应Itl条目lb:都是0x1。即Itl中的第一条。

这时,我们重新访问该数据块:

SQL> alter system flush buffer_cache;

System altered.

SQL> conn demo/demo
Connected.
SQL> select * from t_multiver;

A B
---------- ----------
 1 115
 2 222
 3 222

SQL> alter system dump datafile 5 block 50959;

System altered.

再将数据块内容dump出来:

Block header dump: 0x0140c70f
 Object id on Block? Y
 seg/obj: 0xe46c csc: 0x00.a482a4a3 itc: 2 flg: E typ: 1 - DATA
 brn: 0 bdba: 0x140c709 ver: 0x01 opc: 0
 inc: 0 exflg: 0

Itl Xid Uba Flag Lck Scn/Fsc
0x01 0x0012.02d.0000049c 0x02c00080.0192.0f C--- 0 scn 0x0000.a482a495
0x02 0x000f.01b.00000533 0x02c00054.01bb.0f C--- 0 scn 0x0000.a482a3c3

data_block_dump,data header at 0x7745664
===============
tsiz: 0x1f98
hsiz: 0x18
pbl: 0x07745664
bdba: 0x0140c70f
 76543210
flag=--------
ntab=1
nrow=3
frre=-1
fsbo=0x18
fseo=0x1f4a
avsp=0x1f62
tosp=0x1f62
0xe:pti[0] nrow=3 offs=0
0x12:pri[0] offs=0x1f5e
0x14:pri[1] offs=0x1f4a
0x16:pri[2] offs=0x1f54
block_row_dump:
tab 0, row 0, @0x1f5e
tl: 10 fb: --H-FL-- lb: 0x0 cc: 2
col 0: [ 2] c1 02
col 1: [ 3] c2 02 10
tab 0, row 1, @0x1f4a
tl: 10 fb: --H-FL-- lb: 0x0 cc: 2
col 0: [ 2] c1 03
col 1: [ 3] c2 03 17
tab 0, row 2, @0x1f54
tl: 10 fb: --H-FL-- lb: 0x0 cc: 2
col 0: [ 2] c1 04
col 1: [ 3] c2 03 17
end_of_block_dump
End dump data blocks tsn: 5 file#: 5 minblk 50959 maxblk 50959

这时,可以看到,前一事务的Itl条目中,Flag标志为已经被修改为C,即提交完毕,Commit SCN也被获得。锁也已经被清除,其锁Lck的数量也清0。相应的,各条记录的行锁对应Itl位也被清0

还是图解一下这个过程:

数据块初始状态:

第一个修改该数据块的事务提交后:

第二个访问该数据块的事务(清除了相应锁信息)

当然,如果事务进行的删除操作,或者事务回滚,又会有一些不同的情况。我的另外一篇文章中详细的介绍了延迟块清除这个东东。

1555错误的产生

通过分析Oracle的上面两个特性,我们可以发现会存在这个情况,事务需要读取回滚段已提交数据的信息。这就是出问题的根本原因所在了:当这些数据超出了undo_retention设置的保留时间以后,是不会再被保护的,可能会被其他事务产生的回滚数据覆盖掉。在一致性读的情况下,再去读取被清除的回滚数据信息时,这个快照(snapshot)对于读取者来说就太老了(too old)。在延迟块清除的情况下,再读取Cleanout SCN对应的回滚段事务表中的slot,也会报1555错误了。

此外,如果修改数据块的事务时一个离散事务(discrete transaction, 通过executedbms_transaction.begin_discrete_transaction实现,是一种direct path方式的事务)、或者在使用sqlldr时指定direct=true时,将不会产生回滚信息,也就是说查询语句根本无法获取到回滚信息,因而也会产生1555错误

1555错误发生的情况

下面我们就模拟一下1555错误发生的情况。

测试环境

首先建立测试环境。由于我们只是要模拟1555错误的发生,所以需要建立一个小的回滚表空间,并且设置undo_retention时间为1(秒),以便回滚数据尽快被覆盖(呵呵,要防止1555错误发生,这就一定要避免的)。

CREATE UNDO TABLESPACE rbs_ts

 DATAFILE 'rbs_ts2.dbf' SIZE 10M AUTOEXTEND OFF;



alter system set undo_retention=1 scope=spfile;

alter system set undo_management=auto scope=spfile;

alter system set undo_tablespace=rbs_ts scope=spfile;

startup force

alter tablespace rbs_ts online;

create table demo.t_dual as select * from dual;



insert into t_dual values(1);



commit;



一致性读导致的1555错误

开始读取表。

SQL>
SQL> var cl refcursor
SQL> begin
 2 open :cl for select * from demo.t_multiver;
 3 end;
 4 /

PL/SQL procedure successfully completed.

SQL>

更新表数据,产生回滚信息。

SQL> update demo.t_multiver set b = 111 where a = 1;

1 row updated.

SQL> commit;

Commit complete.

运行大批其他事务,充满所有回滚段,以致覆盖上面的回滚信息。回滚段可以通过dba_rollback_segs查看。

SQL> begin
 2 for i in 1..20000 loop
 3 update demo.t_dual set dummy=1;
 4 commit;
 5 end loop;
 6 end;
 7
 8 /

PL/SQL procedure successfully completed.

SQL> /

PL/SQL procedure successfully completed.

查询到更新过的数据记录,回滚信息已经被覆盖,所以报1555错误。

SQL> print :cl
ERROR:
ORA-01555: snapshot too old: rollback segment number 18 with name "_SYSSMU18$"
too small

no rows selected

SQL>

延迟块清除导致的1555错误

开始读取表。

SQL> var cc refcursor
SQL>
SQL> begin
 2 open :cc for select * from t_multiver;
 3 end;
 4 /

这时一个事务更新了该数据块,但在提交前,我们手工将buffer cache中的数据做了flush,再做提交。这时的数据块上只记录了锁标志,没有事务标志和Commit SCN

PL/SQL procedure successfully completed.

SQL>
SQL> update t_multiver set b=115 where a=1;

1 row updated.

SQL>
SQL> alter system flush buffer_cache;

System altered.

SQL>
SQL> commit;

Commit complete.

进行非常多的事务,将回滚段中的事务信息表中的数据全部覆盖:

SQL>
SQL> begin
 2 -- overwrite rollback slot
 3 for i in 1..40000 loop
 4 update t_dual set dummy=1;
 5 commit;
 6 end loop;
 7 end;
 8 /

PL/SQL procedure successfully completed.

读取数据块前需要到回滚段的事务信息表中读取Itl中没有标记完全的事务的状态和Commit SCN,以判断是否需要进行一致性读。但是事务信息表中的数据都已经被覆盖,所以报1555错误:

SQL>
SQL> print :cc
ERROR:
ORA-01555: snapshot too old: rollback segment number 20 with name "_SYSSMU20$"
too small

no rows selected

以上两个例子看起来是好像很类似,但是,他们的本质区别是:第一个实际上是在进行一致性读得时候发生的1555错误,而第二个例子是在判断是否需要进行一致性读得时候发生的1555错误。

解决1555错误的方法

现在,我们已经知道了1555错误产生的原因。那么,就可以总结出以下方法来解决1555错误问题:

1、扩大回滚段

因为回滚段是循环使用的,如果回滚段足够大,那么那些被提交的数据信息就能保存足够长的时间是那些大事务完成一致性读取。

2、增加undo_retention时间

undo_retention规定的时间内,任何其他事务都不能覆盖这些数据。

3、优化相关查询语句,减少一致性读。

减少查询语句的一致性读,就降低读取不到回滚段数据的风险。这一点非常重要!

4、减少不必要的事务提交

提交的事务越少,产生的回滚段信息就越少。

5、对大事务指定回滚段

通过以下语句可以指定事务的回滚段:

SET TRANSACTION USE ROLLBACK SEGMENT rollback_segment

给大事务指定回滚段,即降低大事务回滚信息覆盖其他事务的回滚信息的几率,又降低了他自身的回滚信息被覆盖的几率。大事务的存在,往往是1555错误产生的诱因。

6、使用游标时尽量使用显式游标,并且只在需要的时候打开游标,同时将所有可以在游标外做的操作从游标循环中拿出。

当游标打开时,查询就开始了,直到游标关闭。减少游标的打开时间,就减少了1555错误发生的几率。

下面例子中,第一段代码发生1555错误的几率就大于第二段的:

差的:

declare 

cursor cl is select b from demo.t_multiver;
v_b number;

begin

open cl; 



--do some thing without relation to the cursor.

fetch cl into v_b;

while cl%found loop
 --do other things without relation to the cursor.
 ... ...

 fetch cl into v_b;

end loop;
close cl; 



commit; 

END; 

好的:

declare 

cursor cl is select * from demo.t_multiver;

begin



--do some thing without relation to the cursor.
--do other things without relation to the cursor.

open cl; 

fetch cl into v_b;

while cl%found loop
 ... ...

 fetch cl into v_b;

end loop;
close cl; 



commit; 

END; 

7、使用回滚表空间自动管理

回滚表空间自动管理是9i后的特性。他由Oracle自动管理回滚段的创建和回收。尽管有人认为这一特性是以后牺牲性能为代价的,或者有其他缺点而不建议使用。但我认为,这确实是Oracle一个很好的特性,特别是OLTP环境下应该使用它。并且10g中,这一特性大大增强了。

而在大型的数据仓库或者报表系统中,会有一些很大的查询作业存在,这时可以考虑使用手动管理,为某些大作业创建单独的回滚段。

以上总结了解决1555错误的各种办法,具体采用哪种方式,就需要根据错误产生的实际情况来决定了。

实例分析

实际上,你在了解了1555错误为什么会发生的前提,遇到了1555错误就不应该再手足无措了。但是,根据我个人的经验,大多数的1555错误的发生,其根本原因还是语句写得太烂,导致了大量的consistent gets和超长的执行时间,最后引发了1555错误。下面就是一个典型例子:

错误的发生

近来生产系统反馈,时常有作业被异常中止,导致应用程序被hung住。经过检查日志,是某个作业在运行时发生了1555错误,导致程序无法返回结果:

* 

ERROR at line 1: 

ORA-01555: snapshot too old: rollback segment number 9 with name "RBS08" too small 

ORA-06512: at "SQLUSER.EXT_PKG", line 4917 

ORA-06512: at line 1 

相关程序记录下的日志:

STAT-S.20060313185536.lg = 2 processed =20060313185536 end date Error = ORA-01555: snapshot too old: rollback segment number 9 with name "RBS08" too small BEGIN ext_pkg.main('extfiles','50','EAT'); END;

错误分析解决

这是一个典型的1555错误。检查引发该错误的PACKAGE,发现它只有一个入口函数main(及程序日志中记录的函数),但这个函数还调用了其他NPACKAGE里面的函数。这是一个大作业,执行时,设置它使用了一个大的回滚段:RBS_BATCH1

先看看相关配置:rollback tablespace空间为8G,undo_retention为1800。

看看回滚段的统计数据:

SQL> Select rn.Name "Rollback Segment", rs.RSSize/1024 "Size (KB)", rs.Gets "Gets",
 2 rs.waits "Waits", (rs.Waits/rs.Gets)*100 "% Waits",
 3 rs.Shrinks "# Shrinks", rs.Extends "# Extends"
 4 from sys.v_$RollName rn, sys.v_$RollStat rs
 5 where rn.usn = rs.usn;

Rollback Segment Size (KB) Gets Waits % Waits # Shrinks # Extends 
------------------------------ ---------- ---------- ---------- ---------- ---------- ---------- 
SYSTEM 952 1189 0 0 0 0 
RBS_BATCH1 409592 681422 667 .097883544 0 0 
... ...S_BATCH1 getshould be provided by DEV Team.r.and CSS_EMAN_INDX exist.eir 
RBS10 204792 478502 10 .002089855 0 0 
RBS11 204792 477366 8 .001675863 0 0 
RBS12 204792 491070 6 .001221822 0 0 
RBS_BATCH2 409592 650088 644 .099063511 0 0 
RBS_BATCH3 409592 243849 3 .00123027 0 0 
16 rows selected.

注意到RBS_BATCHT1的wait%是0.098%,这个值应该是比较好的一个值。

回过头再来看依法错误的语句:调用ext_pkg.main函数。在程序日志中已经记录下了输入参数,这就比较好办了:作一个trace,看看到底哪条语句的性能最差:

SQL> alter system set events ‘10046 trace name context forever, level 1’;

System altered.

SQL> exec ext_pkg.main('extfiles','50','EAT');

PL/SQL procedure successfully completed.

SQL> alter system set events ‘10046 trace name context off’;

System altered.

tkprof处理trace文件后检查trace文件:

TKPROF: Release 9.2.0.5.0 - Production on Tue Mar 14 09:21:58 2006

Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.

Trace file: prod_ora_29225.trc
Sort options: default

********************************************************************************
count = number of times OCI procedure was executed
cpu = cpu time in seconds executing
elapsed = elapsed time in seconds executing
disk = number of physical reads of buffers from disk
query = number of buffers gotten for consistent read
current = number of buffers gotten in current mode (usually for update)
rows = number of rows processed by the fetch or execute call
********************************************************************************

alter session set events='10046 trace name context forever, level 1'

... ...

BEGIN
ext_pkg.main('extfiles','50','EAT');
END;

call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.01 0.04 4 39 0 0
Execute 1 0.20 0.21 24560 37808 0 1
Fetch 0 0.00 0.00 0 0 0 0
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 2 0.21 0.26 24564 37847 0 1

Misses in library cache during parse: 1
Optimizer goal: CHOOSE
Parsing user id: 30
********************************************************************************

... ...

SELECT QID
FROM
 CSQUE QUE, ASTP STP WHERE
 QUE.CDE IN (:B3, :B2) AND QUE.TID =
 STP.TID AND STP.ACDE = :B1 ORDER BY
 QUE.CDE, QUE.DT

call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 2 0.00 0.00 0 0 0 0
Fetch 2682 0.41 0.54 7557 10968 0 2680
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 2685 0.41 0.54 7557 10968 0 2680

Misses in library cache during parse: 1
Optimizer goal: CHOOSE
Parsing user id: 31 (recursive depth: 1)
********************************************************************************

... ...

7 user SQL statements in session.
 41 internal SQL statements in session.
 48 SQL statements in session.
********************************************************************************
Trace file: prod_ora_29225.trc
Trace file compatibility: 9.02.00
Sort options: default

1 session in tracefile.
 7 user SQL statements in trace file.
 41 internal SQL statements in trace file.
 48 SQL statements in trace file.
 20 unique SQL statements in trace file.
 8626 lines in trace file.

trace文件中,发现有一条语句性能相当差,通过对这条语句做SQL Trace,发现它的consistent gets达到80万!

于是对该语句进行优化,调整了它的写法,并建立了缺少的索引(优化过程略)。最终将consistent gets数量降低到了5000

重新安排上线,经过一周的观察,1555错误没再发生。

其实这个案例的解决是比较简单的,最终的处理就是将一条语句进行优化。

分享到:
评论

相关推荐

    expdp 中ORA-39002、ORA-39070错误详解及解决办法

    主要介绍了expdp 中ORA-39002、ORA-39070错误详解及解决办法的相关资料,需要的朋友可以参考下

    OGG之ORA-01403案例

    OGG之ORA-01403案例,包括这个案例所遇到的错误详解,对使用的参数进行了详细的解说

    数据库ORA-01196故障-归档日志丢失恢复详解

    启动数据库时报下面的错误 SQL> alter database open; alter database open * 第 1 行出现错误: ORA-10458: standby database requiresrecovery ORA-01196: 文件 1 由于介质恢复会话失败而不一致 ORA-01110: 数据...

    oracle crs 配置错误详解

    oracle crs 配置错误详解,当我们在安装Clusterware 的时候, 需要在第二节点上vipca , 配置到最后安装的时候, 安装到 75% 左右,报错 检查linux主机名是否符合规范,因为oracle不是直接获取IP地址 ASM装载磁盘组时...

    基于ORA-12170 TNS 连接超时解决办法详解

    1.开始—-程序—–...重新连接又报了另一个错误 ora-12541:TNS:没有监听器1.cmd—services.msc—-以Oracle开头TNListener结尾的服务启动它2.如果还没有启动,修改注册表cmd–regedit找到HKEY_LOCAL_MACHINE/SYSTEM

    oracle详解

    IGNORE 忽略创建错误 (N) RECORDLENGTH IO 记录的长度 GRANTS 导入权限 (Y) INCTYPE 增量导入类型 INDEXES 导入索引 (Y) COMMIT 提交数组插入 (N) ROWS 导入数据行 (Y) PARFILE 参数文件名 LOG 屏幕输出的日志...

    Oracle 10g 学习笔记

    │ 手工配置listener.ora【避免出现ORA-12514错误】.txt │ 贴子树状态存储结构.jpg │ 贴子树状态存储结构.sql │ ├─01 Oracle入门 │ 01 Oracle 简介.txt │ 02 Oracle安装.txt │ 03 sqlplusw的使用.txt │ ...

    oracle 10 Ora 10G 官方文档

    oracle 10G大全,内含DBA认证参考,sql编程指南 常见错误信息详解。绝对经典,值得收藏

    oracle 9i服务器端和客户端安装以及配置详解

    在虚拟机中安装 2003 server 之后,在2003系统中安装数据库, 安装数据库的服务器端 安装数据库的客户端 配置服务器端和客户端 web服务器配置说明 以及错误处理。

    Oracle数据库学习指南

    Oracle2: ...48. 怎样查看init_ora文件 49. 怎样快速查出Oracle 数据库中的锁等待 50. 怎样在SQLPlus中使用 '&' 来实现自定义参数变量? 51. 怎样在查询记录时给记录加锁 52. 自动备份Oracle数据库

    IBM WebSphere Portal门户开发笔记01

    2、JS屏蔽网页错误不在状态栏显示 236 3、浏览器版本的判断 236 4、编写跨浏览器兼容性的JS代码时,常用到的判断代码 237 5、JS 计算网页内容的宽与高 (浏览器的标准模式与怪异模式) 237 6、JS设置与查看网页的解析...

Global site tag (gtag.js) - Google Analytics