Ora-01555产生原因:
1、一致性读导致的ora-01555
当一个较长的查询执行时,查询数据过程中数据块发生了修改,并且被commit后事物量较大,undo segment被覆盖,该查询检索到被修改数据块时,为了一致性读需要去undo中查询数据块前镜像,而该undo segment已经被覆盖所以无法找到数据,此时就会报出ora-01555错误。
2、延迟块清除导致的ora-01555
当数据块被修改后存放到buffer cache中,commit之前进行块清除时使用了延迟块清除(需要清除的数据块较多,超出了buffer_cache的10%,或者在commit之前,已经有dbwr进程将buffer_cache中的数据写入dbwr,比如commit前刷新了buffer cache),被修改的数据块通过dbwr写入数据文件,而每个事务被commit之后会有一个commit scn记录在undo里,select语句发出时会有一个select scn,如果发现select检索的数据块是被延迟块清除的,会通过ITLl事物槽到undo里找对应的该数据库的commit scn,如果此时undo已经被刷新,找不到对应的该数据库的scn,会拿select scn与undo里的最小的commit scn对比,一般来说select scn都会比undo 最小commit scn大,所以会把undo中最小commit scn作为被延迟块清除的数据库的commit scn,这样虽然有真正的该数据库的commit scn不一致,但数据是一直的,所以还是安全的。但是如果真出现比较极端的,select scn比undo里最小的commit scn还要小,那就出现ora - 01555的错误了。
具体过程分析
为了方便演示过程,临时修改一下undo的参数:
SQL> create undo tablespace undotbs02 datafile '/u01/app/oracle/oradata/orcl_dup/undotbs002' size 5m autoextend off;
Tablespace created.
SQL> alter system set undo_tablespace=undotbs02 scope=spfile;
System altered.
SQL> alter system set undo_retention=3 ;
System altered.
undo_retention参数用来控制undo数据的保留时间,默认的是900s,此处改为3s只是为了方便测试,更加详细的讲解请参照http://blog.itpub.net/17203031/viewspace-774498
10203事件用来跟踪块的清除操作
SQL> alter system set event='10203 trace name context forever' scope=spfile;
System altered.
SQL> shutdown immediate;
Database closed.
Database dismounted.
ORACLE instance shut down.
SQL> startup
ORACLE instance started.
Total System Global Area 1677721