ITPub博客

首页 > 数据库 > Oracle > oracle 9i下ORA-01555错误的解决方法

oracle 9i下ORA-01555错误的解决方法

原创 Oracle 作者:sky_dizzy001 时间:2014-02-11 09:08:55 0 删除 编辑
导致ora-01555的原因

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

2、延迟块清除
另外一个可能产生1555错误的概念——延迟块清除(Delayed Block Cleanout)。但个人认为,如果不从字面意思上翻译,应该把它叫做延迟锁清除更加让人容易理解一些。
我们知道,当Oracle更新数据块时,会在回滚段(UNDO Segment)记录下这一更新动作。并且产生一个Cleanout SCN,在回滚段中,会产生对应的Transaction ID以及相应的数据记录镜像。并在对应的数据记录上,产生锁标志。在事务提交(commit)前,会在数据块的头部记录下这个Cleanout SCN(Csc)号、Undo Block Address(Uba)和Transaction ID(Xid);并且在在对应Interested Transaction List(Itl)中设置锁标志,记录这个事务在这数据块中产生的锁的数目;同时在对应修改的数据记录上打上行级锁标志,并映射到对应的Itl去。当提交时,并不会一一清除掉所有锁标志,而是给对应的Itl打上相应标志,告诉后面访问该数据块的事务,相应的事务已经提交。这就叫做快速提交(Fast Commit)。而后面访问该数据块的的事务就先检查锁标志和对应的事务状态,如果发现前面的事务没有提交,并且要访问的数据记录被锁住了,就被阻塞;否则就清除相应的锁标志,并提交自己的锁标志,再重复以上动作。这就是延迟块清除。
而如果前面的事务在提交之前buffer cache中的脏数据已经被DBwn进程写回,那么Itl中的事务标志就不会被更新,并且数据块的Itl列表也不会记录下事务的Commit SCN。后面的事务或查询语句访问该数据块时,为了检测是否需要进行一致性读(如果数据块的Itl中记录的提交事务的Commit SCN大于当前访问该数据块的SCN,则需要进行一致性读),就需要通过Undo Block Address和Transaction ID到回滚段的事务信息表中去检查前面事务的状态和它的Commit SCN,确定是否做一致性读,最后将前面事务在该数据块上的标志做一次Cleanout。

解决ora-01555错误的方法
 
1、扩大undo表空间
因为回滚段是循环使用的,如果回滚段足够大,那么那些被提交的数据信息就能保存足够长的时间是那些大事务完成一致性读取。
 
2、增加undo_retention时间
在undo_retention规定的时间内,任何其他事务都不能覆盖这些数据。
 
3、优化相关查询语句,减少一致性读。
减少查询语句的一致性读,就降低读取不到回滚段数据的风险。这一点非常重要!
 
4、减少不必要的事务提交
提交的事务越少,产生的回滚段信息就越少。
 
5、使用游标时尽量使用显式游标,并且只在需要的时候打开游标,同时将所有可以在游标外做的操作从游标循环中拿出。当游标打开时,查询就开始了,直到游标关闭。减少游标的打开时间,就减少了1555错误发生的几率。

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/29468144/viewspace-1079263/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2014-02-01

  • 博文量
    27
  • 访问量
    129617