ORA-1555经典的错误

现象:

应用的夜维从夜里00:00开始执行,但因为hang的原因(暂时猜测为夜维处理的某条数据和当前应用正常处理的某条数据相同,出现前后等待同一资源锁的现象),直到第二天白天09:25左右才继续执行,但此时应用日志记录:

snapshot too old: rollback segment number 29 with name "_SYSSMU29$" too small

原因分析:

因hang导致夜维的DELETE语句一直处于等待状态(超过一天),直到资源锁释放,但此时由于开始存放于UNDO中的前镜像超过UNDO_RETENTION参数设置的时间,且这是高并发的一个系统,很快可能就会被应用session覆盖UNDO中的记录,导致无法找到UNDO中的记录产生一致性读,因此报错ORA-1555,此次执行失败。

虽然分析可能是这个原因,但是是什么语句让这个系统的夜维语句hang,还没有找到,有待进一步分析。。。

引申:

不过从这个报错现象可以接触到ORA-1555这个经典的错误号,尤其是在生产中,也是一种不多见的情况,尤其在现在UNDO基本都是用Oracle自动管理方式,且磁盘空间分配都比较大的情况下。

这个ORA-1555的错误是Oracle回滚段错误中的一种经典。UNDO用于记录DML操作数据的前镜像,ORA-1555的错误简单用一句话总结,我觉得就是当DML语句需要用UNDO记录的数据找到前镜像时,该记录已经被覆盖,导致无法利用UNDO中的记录完成一致性读。当然Oracle也有UNDO_RETENTION等参数避免这种情况的产生,但仍旧可能发生,原因有多种,解决方法也有多种,下面就简单说明介绍下。

首先,Tom、hellodba等高人也对ORA-1555有过经典的介绍。从原因来讲,ORA-1555的错误原因归为两种,一是一致性读,一个是延迟块(锁)清除。

和ORA-1555相关的参数:

1、UNDO_RETENTION。

UNDO_RETENTION参数设置了回滚段中被提交或回滚的数据强制保留时间,但并不是说超过这个时间,回滚段中的数据就会被清除,而是等待后面的事务产生的回滚数据覆盖之前的。

2、对于Oracle 9i及以上版本,有两种管理UNDO的方法,由UNDO_MANAGEMENT参数指定,手动管理UNDO和自动管理UNDO的区别:手动管理是会回绕的,会尽可能地重用UNDO空间,Oracle会扩展UNDO段,而不是回绕,从而保证UNDO_RETENTION的时间要求。因此从这可以看出,为了避免ORA-1555,使用自动管理UNDO的方法也许可以一定程度上降低概率。

概念介绍:

1、一致性读(摘自hellodba的blog:“http://www.hellodba.com/reader.php?ID=170&lang=CN”)

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

2、延迟块清除(摘自hellodba的blog:“http://www.hellodba.com/reader.php?ID=170&lang=CN”)

当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)。而后面访问该数据块的的事务就先检查锁标志和对应的事务状态,如果发现前面的事务没有提交,并且要访问的数据记录被锁住了,就被阻塞;否则就清除相应的锁标志,并提交自己的锁标志,再重复以上动作。这就事延迟块清除。

如果大事务接触到了非常多的块,并且到了缓冲区缓存的10%以上,此时就会出现待清理的块,并未由COMMIT操作清理,即不是FAST COMMIT,没有其它事务DML接触这些块,而是SELECT一个表时就有可能出现ORA-1555的错误。

另外,看到网上很多验证ORA-1555的错误实验,都是用SELECT语句测试的,但其实应该是“事务”或“查询”语句需要UNDO中数据时,出现记录被覆盖的情况下都有可能报这个错,因此开始介绍的夜维报错就是DELETE语句报的ORA-1555,且这个夜维比较特殊的地方就是他是若干条(22条)DELETE语句在一个事务中,即都执行完成后才一次COMMIT,这样无形当中增加了事务的复杂度,但凡其中一条语句等待,则其他语句就无法提交,也只能等待,虽然这是由业务决定的,但这种情况还是应该避免,当然这是另一个话题了。

实例:UNDO空间太小导致的ORA-1555

创建一个2M大小,不能自动扩展的UNDO空间。

SQL> create undo tablespace undo_small datafile '/opt/oracle/oradata/bisal/undo_small.dbf' size 2m autoextend off;

将其设置为系统UNDO空间。
SQL> alter system set undo_tablespace = undo_small;
System altered.

创建一张测试表。(注意:这里使用dbms_random.random是为了将行弄乱,使他们不至于认为有某种顺序,从而得到随机的分布,因为CTAS方式建表是力图按照查询获取的顺序将行放在块中。)
SQL> create table t as select * from all_objects order by dbms_random.random;
Table created.

创建主键。
SQL> alter table t add constraint t_undo_pk primary key(object_id);
Table altered.

收集表的统计信息。
SQL> exec dbms_stats.gather_table_stats(user, 'T', cascade=>true);
PL/SQL procedure successfully completed.

重复更新表中所有数据。

SQL> begin
        for x in (select rowid rid from t)
        loop
  update t set object_name = lower(object_name) where rowid = x.rid;      
  commit;
  end loop;
  end;
  /
PL/SQL procedure successfully completed.

上述语句执行过程中,创建查询语句,这里使用DBMS_LOCK.SLEEP(0.01)来模拟查询单次时间是0.01秒,由于是随机插入到表中的,因此此处相当于随机地查询表中的块。这个查询语句执行几秒就可能失败。
declare 
cursor c is
  select /*+first_rows*/ object_name
  from t
  order by object_id;
  
  l_object_name t.object_name%type;
  l_rowcnt number:=0;
    begin
  open c;
  loop
  fetch c into l_object_name;
  exit when c%notfound;
  dbms_lock.sleep(0.01);
  l_rowcnt := l_rowcnt + 1;
  end loop;
  close c;
    exception
  when others then
  dbms_output.put_line('rows fetched = '|| l_rowcnt);
  raise;
end;
/
(注:报错

l_rowcnt number:=0;
  *
ERROR at line 8:
ORA-06550: line 8, column 4:
PLS-00103: Encountered the symbol "L_ROWCNT" when expecting one of the
following:
:= ( ; not null range default character
The symbol ";" was substituted for "L_ROWCNT" to continue.
可能是l_object_name t.object_name%type少分号)

报错是:

declare
*
ERROR at line 1:
ORA-01555: snapshot too old: rollback segment number 11 with name "_SYSSMU11$" too small
ORA-06512: at line 21

总结:
对于报错,原因在于SELECT语句是按照object_id的索引进行读取,(INDEX FULL SCAN),由于之前数据是按照随机顺序插入得到的,因此此处是在全表上执行随机读,这样就可能出现:SELECT读到的数据可能是不同块中的,此时UPDATE更新数据并提交,标识UNDO中该记录可被覆盖,由于UNDO空间较小,因此出现SELECT读取的UNDO块被UPDATE更新、提交而被覆盖的可能性就会变大,于是出现了ORA-1555的错误。

为了解决这种问题,将UNDO设置为可扩展,让Oracle自动管理UNDO,可以最大幅度地扩展UNDO容量,满足UNDO_RETENTION时间要求的同时,也保证了SELECT可以读到的块不会被UPDATE提交所覆盖。
SQL> column file_name new_val F
SQL> select file_name from dba_data_files where tablespace_name='UNDO_SMALL';
FILE_NAME
--------------------------------------------------------------------------------
/opt/oracle/oradata/bisal/undo_small.dbf

SQL> Alter database datafile '&F' autoextend on
  2  next 1m        
  3  maxsize 2048m;
old   1: Alter database datafile '&F' autoextend on
new   1: Alter database datafile '/opt/oracle/oradata/bisal/undo_small.dbf' autoextend on
Database altered.

SQL> select bytes/1024/1024 from dba_data_files where tablespace_name='UNDO_SMALL';
BYTES/1024/1024
---------------
     4

此时再执行上述UPDATE和SELECT语句,即可执行完成。

时间: 2024-08-26 08:25:29

ORA-1555经典的错误的相关文章

Oracle ORA 07445 evaopn2()+128错误问题的解决方案_oracle

问题描述 Plsql developer执行一段sql报错: 经查alert log详细报错信息为: ORA-07445: exception encountered: core dump [evaopn2()+128] [SIGSEGV] [Address not mapped to object] [0x000000000] [] [] 数据库版本 10.2.0.4.0 问题原因 复杂视图合并问题导致的oracle bug 解决方法 1.修改隐藏参数: alter system set "_

10种经典的错误提示信息

译文来源:10种经典的错误提示信息

GoldenGate中如何使用reperror进行错误处理

对于Replicat进程处理DML操作过程中报错时,GoldenGate提供了一个参数用来控制如何处理Replicat进程的报错.这就是本节内容要介绍的reperror参数.这个参数能控制大部分的GoldenGate错误处理的手段. 如某案例的Replicat进程参数如图1所示. 图1 1.reperror处理类型与含义 Reperror在GoldenGate11版本中共提供了7类处理错误方式,分别如下. (1)abend:Replicat遇到不能处理的记录时,回滚事务,然后停止处理,Repli

轻松解决宽带错误不求人!宽带连接错误代码678问题解决经验

您是否遇到过 宽带连接错误678,远程计算机无响应,在网上查找的答案都是长篇一律,网卡灯亮不亮.lan灯亮不亮...,那些个答案都过时了!下面 错误网http://www.cuowuyemian.com/ 总结了时下经测试确实可行的几种情况及其解决方法,让你轻松解决宽带错误不求人! PS:经典错误678解决方法详见 http://www.cuowuyemian.com/201110/cuowu678.html 一.突然出现错误678 电脑未做过任何变动,突然就出现错误678,并且可能电话也忙音打

【OGG】OGG故障错误处理总结

[OGG]OGG故障错误处理总结 第一章 GoldenGate错误分析与处理 在维护GoldenGate过程中,由于各种意外情况,难免还是会遇到各种各样的问题.掌握一些常见的GoldenGate故障诊断和错误分析的方法是非常有必要的,而且掌握这些错误分析工具也进一步加深对GoldenGate产品的认识与对GoldenGate原理的理解.   1.1   GoldenGate常见异常处理 GoldenGate运行起来后,随着时间的推移可能会碰到各种各样的问题,下面就来介绍常见的异常现象以及常见的异

ORA-03113错误分析

错误 Fenng(Fenng@itpub.net) 版权声明:转载请注明作者及出处 前言 每一个DBA在进行数据库管理的过程中不可避免的要遇到形形色色的错误(ORA-xxxx).有些错误由于频繁出现.原因复杂而被DBA们戏称之为"经典的错误".其中ORA-3113 "end of fileon communication channel" 就是这样的一个. 我们可以简单的把这个错误理解为Oracle客户端进程和数据库后台进程连接中断.不过,导致这个错误的原因实际上有

oracle Exadata火线救援:10TB级数据恢复—强制拉库篇

这个库的恢复有一些历史故事([力荐]Exadata火线救援:10TB级数据修复经典案例详解!):xx运营商x2的1/4配置的oracle exadata机器,跑了近6年,最近有一个cell节点主机异常,在rebalance过程中,只有两个节点的cell其中一个节点坏了一个硬盘导致.导致asm diskgroup无法正常mount,最后该运营商运维三方通过amdu把该一体机中的数据文件全部抽出来,然后在恢复过程中出现大量错误无法解决,请求我们支持 数据库open过程报ORA-01555错误 Thu

ORA-03113错误分析与解决

前言 每一个DBA在进行数据库管理的过程中不可避免的要遇到形形色色的错误(ORA-1547 ,ORA-904,ORA-1578 ......).有些错误由于频繁出现.原因复杂而被 Oracle DBA 们戏称之为"经典的错误".其中ORA-3113 "end of file on communication channel" 就是这样的一个. 我们可以简单的把这个错误理解为Oracle客户端进程和数据库后台进程连接中断.不过,导致这个错误的原因实际上有很多种:对数据

关于ORA-01555的问题分析

今天开发的同事发给我一个问题,在运行某一个Job的时候抛出了ORA错误,希望我们看看从数据库层面能不能发现什么. 错误日志如下: Function: EntitySQLCursor::query Line number: 113 Time: Thu Jul  2 22:52:46 2015 Message text: (PE1-000143) Internal IO Framework Database Error, message ORA-01555: snapshot too old: ro