Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1104460
  • 博文数量: 159
  • 博客积分: 3063
  • 博客等级: 中校
  • 技术积分: 2703
  • 用 户 组: 普通用户
  • 注册时间: 2012-04-01 01:51
文章分类

全部博文(159)

文章存档

2013年(48)

2012年(111)

分类: Oracle

2012-04-18 21:34:10

ORA-1555错误简单的说就是针对一个数据块产生一致读时发生了错误。一致读就是指ORACLE利用回滚段来临时重构一个和事务或查询开始时的 块状态相同的快照块的过程。如果一个块改变了多次,可能就会有多个快照块的。
    一个事务或查询开始执行时,ORACLE会产生一个SCN来记录这个开始时刻点,这个SCN也就叫做SNAPSHOT SCN。ORACLE仅仅看基于SNAPSHOT  SCN的快照记录。如果块中有活动的事务或BLOCK SCN> SNAPSHOT SCN时,就产生了一致读。如果是没有活动的事务但没有产生COMMIT SCN的块 ,先产生DELAY BLOCK CLEANOUT,再比较COMMIT SCN与SNAPSHOT SCN的大小,如果COMMIT SCN小于SNAPSHOT SCN则直接使用该块,否则要产生一致读。
产生ORA-1555的可能情况:
    1 一个长时间运行的查询,并同时针对查询需要的块有DML处理(主要是update和delete)  
    2 当查询和插入并发时
    3 延迟块清除
    4 交叉fetch和commit
    5 回滚段发生错误
情况1 一个长时间运行的查询,并同时针对查询需要的块有DML处理(主要是update和delete)
    当一个查询开始之后,正好某一个update更改了其中的一个记录,当查询扫描到该记录时,就需要一致读,回滚空间中去查找原值。如果这个查询的时间非常长,而那条记录修改之后,很快就被提交了,导致回滚空间中的记录可以被清除,并且这个数据库事务本身也比较多,回滚空间的覆盖比较块,在查询结束之前,回滚段中的记录空间就被新的记录覆盖占用了,导致查询找不到原值,从而产生ORA-1555错误。
        Solution:
    1、业务控制,禁止对同一个表的长时间查询和更新处理同时进行,要分开执行
    2、增大回滚段的大小
    3、增加回滚段的个数
    4、不使用OPTIMAL选项,已经被使用的空间就不会很快收缩回来,可以使commit之后的记录保持尽可能长的时间
    5、推迟对DML语句的COMMIT
    6、优化查询语句,比如并行查询,目的是减小查询的时间
    7、为要查询的表建立只读SNAPSHOT,这样对表记录的修改就不会影响到查询,但该表不能是太大的表
情况2 当查询和插入并发时
    一般情况下,当我们查询一个表,同时对这个表作插入,这时是不需要一致读的。当然这种情况下也不可能产生ORA-1555错误。
    当作全表扫描的时候,oracle会扫描所有位于HWM之下的空间,而对于HWM之上的空间将忽略。也正因为如此,当我们插入的数据位于HWM之下的时候,如果同时还有例如全表扫描这部分空闲的空间,就会产生一致读,就有可能会导致ORA-1555错误。 特别是在VLDB和OPS系统中,因为在这些系统中,很多时候都会对表作pre-allocate,当作了预分配之后,如果作一次大批量的delete,将会有非常多的可用空间位于HWM之下。
    Solutions:   
    1、情况1的所有解决方法这里同样适用
    2、不要预分配区(pre-allocate extent)
    3、使用tuncate来删除表记录,使HWM收缩。
    4、使用直接路径选项导入数据,使插入的数据在HWM之上。
情况3 延迟块清除
    关于延迟块清除的概念,可以参考后面的附录。
    Solution:
    1、使用oracle并行服务器OPS,将DML操作分割到不同的实例上执行  
    2、在批处理中使用SET TRANSACTION USE ROLLBACK SEGMENT为事务单独指定一个回滚段。
    3、可以在DML之后,立即执行一个全表扫描和analyze indexes来强制立即进行块清除。
情况4 交叉fetch和commit
    这种比较典型的情况是在一个过程中使用了如下的结构:
    cursor c1 is select * from bigemp;
    begin
    for c1rec in c1 loop
update mydual set a=a;
commit;
    end loop;
    end ;
    Solution:
    1、检查过程,避免这种交叉提取和提交的情况出现。
    2、延迟commit
    3、在查询语句中,增加“ order by 1 ”的语句,这样会在临时段中保留ORDER BY的结果,可以避免一些一致读。
情况5 回滚段发生错误的解决方法:
    由这种原因导致的ORA-01555错误是极少数的。一般情况下,也只有在那些不支持大文件的操作系统会发生这种情况。
    Solution:
    1、检查init.ora中的参数文件,show parameter CORRUPT,可以将结果提交给ORACLE SUPPORT SERVICES。如果这样的参数存在,建议重 建数据库。
    2、检查操作系统是否支持ORACLE。检查操作系统的错误日志和ORACLE的错误日志。
    3、向Oracle Support Services寻求帮助。
补充情况6:
    在oracle 9i之后,使用auto的undo,就很少出现ORA-1555错误了,但是也不能完全排除这个错误,比如以下错误:
ORA-01555 caused by SQL statement below (Query Duration=11952 sec, SCN: 0x0842.1a1d737c)
    这种情况下,主要是查询的时间超长,超过了undo_retention设置的时间10800秒,从而产生前面的情况1和情况2的错误。
    Solution:
    主要的解决方法,还是优化查询,包括语句的优化和索引的优化。

阅读(3277) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~