ORA-01555
0. 开始先看看rollback segment是否有分配不当的问题,例如莫一个rollback segment(报错的那个)太小。
如果有,先recreate rollback segment以保持所有的回滚段大小一致,并且size不要太小。
1. 看查询的执行计划是否正确。ORA-01555错误发生的概率和查询所需的时间成正比,查询时间越长,发生ORA-01555的概率越大。
如果执行计划不正确,首先进行sql tuning,如果执行计划正确,但进行fts,考虑是否可以并行来跑(server load不是很高的情况下)
总之一句话就是尽量缩短query的时间
2. 如果执行计划正确,估算一下运行时间,如果运行时间不是很长,这时候我喜欢登陆到server本地上执行一下SQL看看需要多少时间
如果本地很快就执行完了,说明问题出在application媏,转入下面第三点。如果确实很慢,转入第四点。
3. Application媏的问题可能类型很多,我所遇到的大致有一下几种
3.1 网络速度太慢,application server和database server的网络出现问题。这时候dba可以从application server断来做一些ping包的测试。
如果确实是网络的问题,可以找网络工程师协助察看是否有网络故障。如果异地之间确实速度很慢,可以考虑是否从一台速度比较
快的application server上发出查询请求。
3.2 Cursor open时间太长。有时候application媏是使用open cursor的方式来fetch data。这时候有可能open cursor后长时间不做操作,导致fetch data时
出现ORA-01555。更常见的一种情况是,有些应用是将一些处理程序放置在fetch loop中,例如
declare
cursor cur_query is select object_id from dba_objects;
…..
begin
for i in cur_query loop
….
&do some things here
…
end loop;
end;
/
这时候可能整个查询的速度被”&do some things here“这段处理程序的速度所影响,导致整个查询速度变慢。
可以建议application修改code,将数据先fetch出来存在一个structure中,然后再来处理。
3.3 commiting in a loop,这一点在Tom kyte的Expert Oracle Database Architecture中有详细的例子(P268),在itpub上有一篇帖子遇到的就是这个问题。
4. 这时候我们要考虑一下数据库本身了。首先看看产生这么多undo 信息是否正常,如果正常的话,考虑是否可以挑选一个系统比较空闲的时段跑查询。
如果本身查询运行的时间就是系统比较空闲的时段或者系统从来就没闲过:), 那就加大回滚段吧。
这里有两种方法,
第一种是重建回滚段,修改minextents为一个较大的值,一个一个的offline,drop,create。初始化的大小为minextents*extent size
第二种是增加回滚段的个数
8i在有些情况下oracle会很喜欢用第一个回滚段,不知道为何,可以考虑将第一个回滚段扩大一点(如果错误信息里面是第一个回滚段的话)
我比较喜欢使用的是第一种方法
5. 如果第四步仍然没有效果(我们不可能无限制的加大回滚段),那么可以考虑其他的方法
如果有standby database的话,可以考虑将其open read only来给大的查询使用,或者为其建立一个报表系统
对于ORA-01555比较频繁的系统,可以考虑转为auto management undo tablespace,这样管理起来简单一点。
auto管理下处理的基本思想是,获得最长查询的时间,预估keep这段时间undo所需的回滚段大小,扩大undo tablespace,修改undo_retention
这里推荐一篇文章讲解auto undo management的文章,讲解还是比较详细的 auto undo management.pdf (右键点击下载)
另外关于LOB存在的情况,是完全不同的一种情况,我以前有文章写过 ,请参考 当ORA-01555遇到了LOB
当然这里短短的描述还是不能涵盖ORA-01555 。实际处理问题的时候也不必拘泥于具体的步骤。
理解了基本原理,再辅以实际案例的解决,这样才会有一个真正意义上的理解。