ORA-01555的主要发生原因以及应对方法

本文地址: https://www.askmac.cn/archives/ora-01555.html

如果自己搞不定可以找诗檀软件专业ORACLE数据库修复团队成员帮您恢复!

诗檀软件专业数据库修复团队

服务热线 : 13764045638 QQ号:47079569 邮箱:service@parnassusdata.com

 

说明ORA-1555的主要发生原因以及应对方法。

[错误信息]

 

ORA‐01555 snapshot太旧了:回滚段编号string、名字 “string”太小

 

‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐

 

原因:一致读入中所需要的回滚记录被其他用户覆盖了

 

对应方法:使用自动UNDO管理模式时,请增加UNDO_RETENTION的设定值。不使用时,请使用更大的回滚段。

 

 

 

 

[技术说明]

 

‐ 错误内容的解读以及发生错误时的对应方法

 

错误内存因为oracle读取一致性所需要的Before-image被覆盖了等等理由没有获得成功,就会作为错误输出。回滚段(后文中是RBS)是由很多的UNDO块变成的,Before-image被储存在UNDO块上。

 

一般而言,错误原因是以下两点。

 

  1. RBS的数量因为尺寸不够,需要读取一致性的Before-image就被覆盖了

 

  1. 发生ORA‐1555 的SQL执行了较长时间(cursor的话,从启动后经过了较长时间)

 

ORA‐1555发生时,首先想到的对应方法是重新执行ORA-1555所发生的处理。大部分情况,通过重新执行,可以回避ORA-1555的错误。

 

但是,如果是使用只读事务,发生块故障,media故障等即使重新执行也会发生ORA-1555所以需要终止那个事务,修复故障等。

 

重新执行也会反复发生ORA-1555的案例中,请以这次的文章中所展示的基本的对策、详细的原因以及解决方法为参考,去除引发ORA-1555的原因。

 

  • 抑制ORA‐1555发生的对应方法,如下所示。

 

  1. Oracle8i 以前,UNDO_MANAGEMENT=MANUAL 的情况

 

  • 增加RBS的数量、尺寸

 

Oracle9i 以后, UNDO_MANAGEMENT=AUTO的情况

 

  • 增加undo表区域的尺寸

 

  • 增加初始化参数UNDO_RETENTION 的值。UNDO_RETENTION参数在commit之后,保存UNDO信息的期间(单位:秒)。但是,无法充分确保UNDO区域时,因为需要保持的UNDO会被覆盖,所以需要配合UNDO表区域的尺寸来增加。
    • 基本而言,ORA-1555在搜索语句中发生时,将那个搜索语句的执行所耗费的时间UNDO_RETENTION设定为更大的值。用UNDO_RETENTION指定的期间的UNDO为了课可以保存,几乎在很多的案例中都可以通过增加undo表区域尺寸来抑制该问题的发生。

 

  1. 重新审视应用以及条约

 

  • 减少长时间启动的SQL语句以及cursor

 

  • 发生ORA‐1555的SQL语句的执行中,抑制其他事务的更新处理,就会变得很难覆盖其他必要的UNDO块。

 

  • 错误内容的详细说明

 

Oracle中最低也会在各个SQL语句中保证读取一致性。换言之,用户会返回保证了发行SQL语句时的一致性的数据。因此,执行搜索的用户不会发现在搜索中被其他用户变更的数据。

 

Oracle根据系统变更编号System Change Numbers (SCN),可以识别数据库的状态。因为SCN发生了commit,随着时间肯定会增大。使用这个SCN可以实现读取一致性。

 

读取一致性是通过RBS来实现的。

 

事务多次变更时,Before-image会储存在RBS上的UNDO块中。和名字一样,使用Before-image会执行回滚。在数据库的一部分头中,会记录哪里的RBS的UNDO块被使用了。同样地,数据库会保存最后被commit的SCN的值。

 

由此,搜索中,其他用户改写了数据,使用UNDO块,通过回滚被改写的数据,其用户可以读取更新前的before image。

 

这些before image在保存时,对执行更新的事务进行commit。在commit事务时,虽然并不是删除UNDO块的内容,使用过的UNDO块,通过新发行的事务等使用,就会被覆盖删除。

 

ORA-1555的内容就是因为读取一致性,试着读入使用UNDO块的其他事务的变更前的数据,但已经无法获得储存了必需的数据的UNDO块了。

 

因此读取一致性,为了减少查看旧UNDO块信息,可以减少事务的执行时间。或者,为了防止必要的UNDO块被覆盖,一般的对应方法就是扩大RBS。

 

 

[原因的指定方法]

 

发生这个错误时,请考虑以下原因。

 

详细内容请查看后述记载,为了推测到底是什么原因引发了错误,需要收集以下信息。

 

  1. 在那个SQL语句中发生了ORA-1555

 

这是应用的日志中,发生了ORA-1555时,指定执行过的SQL语句。

 

Oracle9i Database Release2 以后的版本中,发生ORA-1555时以下的信息就会被警报日志记录,这时发生了ORA-1555时,我们就可以知道执行过的SQL。(除去后述(原因4)的LOB的案例以及不是执行中的SQL语句的案例(比如:直接路径输出))

 

Wed Jul 30 15:04:53 2003

 

ORA‐01555 caused by SQL statement below (Query Duration=1 sec, SCN: 0x0000.000253f2): Wed Jul 30 15:04:53 2003

 

select c1 from t1 where c2=’1′

 

在这里的例子中,会表示出 Query Duration 。UNDO_MANAGEMENT=AUTO 的情况时,比记录于此的数值在UNDO_RETENTION中设定得更大。

 

 

在以前的发行中,会在初始化参数中会追加以下内容。

 

event=”1555 trace name errorstack level 1″

 

重启数据库之后,发生ORA-1555时,就会输出追踪文件。就会在开头中记录以下发生ORA-1555时的SQL语句。(但是排除后述【原因4】的LOB的案例以及不是执行中的SQL语句的案例(比如:直接路径输出))。

 

  • SESSION ID:(8.24) 2003‐07‐31 20:14:24.950

 

  • 2003‐07‐31 20:14:24.950

 

ksedmp: internal or fatal error

ORA‐01555: snapshot too old: rollback segment number 2 with name “???” too small Current SQL statement for this session:

 

select c1 from t1 where c2=’1′

 

  1. 到底是哪个RBS中发生了ORA-1555 (UNDO_MANAGEMENT=AUTO 的话不需要检查)

 

一般来说,错误信息中,因为记录了RBS的编号以及名称,请利用这个。

 

ERROR at line 1:

 

ORA‐01555: snapshot too old: rollback segment number 2 with name “RBS2” too small ORA‐06512: at line 2

 

仅仅记录了编号时,RBS的名称通过以下SQL语句来指定

 

SQL> select segment_name from dba_rollback_segs where segment_id=<rbs number>;

 

SEGMENT_NAME

‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐

RBS2

 

[发生原因以及对应方法]

 

ORA‐1555 发生的原因如下所示。在此,我将叙述发生原因以及对应方法。

 

以下的例子中,请读出接下来两个开头。到底是哪个cursor、SELECT语句接受了ORA-1555。

 

・RBS中没有发现的是哪个处理哪个信息。

 

(原因1)

 

最典型的案例

 

耗费时间的搜索在执行搜索时,其他事务就会更新,执行commit的情况。

 

SCN TransactionA(TRAN:A) TransactionB(TRAN:B)   Other Transactions
10 select … from TabA
20 : update TabA
30 : commit
40 : select执行中 多数的更新、commit
:
50 ORA‐1555

 

这个案例中,TRAN:A是 SCN:10 开始搜索。根据读取一致性的规则, TRAN:A必须读入SCN:10 的时点中的TabA的数据。但是,由于TRAN:B, SCN:20中,TabA会被更新,之后就会进行commit。TRAN:A是由于TRAN:B在读入变更前的数据,需要TRAN:B所使用额RBS的内容,但是因为TRAN:B已经在commit了,因此就会发生了ORA-01555。

 

另外,在上述例中,变成了select执行中。Oracle在搜索中,需要不少时间的案例,但SCN:10启动cursor,之后,与经过SCN:50执行fetch的案例相同。

 

(对应方法1)

这个案例中,原因有以下三点。

  1. TRAN:A长时间执行SQL,或者长时间启动cursor
  1. 将TRAN:A所执行搜索的表在TRAN:B中执行更新
  1. TRAN:B所使用的UNDO块会被覆盖或者被开放

因此,对策如下

 

  1. 为了减少ORA‐1555发生的搜索处理会重新审视搜索语句的调优以及应用。

 

  1. ORA‐1555发生的搜索的执行中,对于搜索对象表不执行更新处理

 

  1. UNDO块的覆盖或者抑制开放

 

Oracle9i 以后, UNDO_MANAGEMENT=AUTO的情况:

  • 增加初始化参数 UNDO_RETENTION的值
  • 增加undo表区域的尺寸

 

Oracle8i 以前,UNDO_MANAGEMENT=MANUAL的情况:

  • 增加RBS的数量、尺寸
  • 重新准备较大的RBS, TRAN:B中明确分割那个较大的RBS。 (使用SET TRANSACTION ROLLBACK SEGMENT …)
  • 设定OPTIMAL时,扩大那个设定

 

(原因2)

通过插入commit使用cursor的案例

 

Oracle的方法中,启动cursor后,即使是执行commit时,然后利用那个cursor,可以继续执行fetch可以推测以下案例。

 

SCN SessionA(SESS:A)
10 open cursor (select … from TabA)
20 fetch row
30 update TabA, commit
40 fetch row
50 update TabA, commit
60 fetch row
:
70 fetch row ‐‐> ORA‐1555

 

这时,cursor中取出的记录是SCN:10的时点的TabA的数据,不会反映SCN:30以及SCN:50的内容。因此,从cursor取出记录时,需要读入SCN:30以及SCN:50变更前的数据。这时,SESS:A自身就是原因1中的完成SESS:A以及SESS:B二者的功效。SCN:30以及SCN:50更新是所使用的RBS丧失时,就会发生ORA-1555。

 

 

(对应方法2)

 

这个案例中,主要原因是以下两个要素。

 

  1. 对成为cursor搜索对象的表进行更新

 

  1. 更新之后,因为执行了commit,undo块会被覆盖或者被重新开放。

 

 

因此,对应方法如下所示。

 

  1. 为了不要重新执行搜索与更新,请重新审视应用

 

  1. 不进行commit,或者减少commit的次数,可以降低UNDO块被覆盖的可能性

 

  1. 防止UNDO块被覆盖

 

Oracle9i 以后 UNDO_MANAGEMENT=AUTO时

 

  • 增加初始化参数 UNDO_RETENTION 的值

 

  • 增加UNDO表区域的尺寸

 

Oracle8i 以前,UNDO_MANAGEMENT=MANUAL 时

 

‐ 增加RBS的数量与尺寸

 

  • 重新准备较大的RBS,对TRAN:B分配较大的RBS

(使用SET TRANSACTION ROLLBACK SEGMENT …)

 

(原因3)

 

与block client相关的案例

 

上述的两个案例中,都在发生发生oracle-1555搜索的执行中,对成为搜索对象的表进行更新。但是,如果与block clean out相关的话,并不一定需要对搜索执行中的相同的表进行更新。

 

事务的commit信息保存在数据块以及事务表两个地方。这个信息中包含是否被commit以及commit时的SCN等信息。更新数据之后,进行commit时,RBS中一定会记录commit信息。但数据块中并不一定会记录commit的信息。这是为了让commit能够高效完成。在其他的事务中,对应的数据库搜索时,对应的数据块被搜索到时,就会发生“block clean up”。这时,数据块的事务信息就会被更新,在数据库中也会表示已经被commit了。执行了commit的SCN,或者至少在这个SCN中记录为commit完成的信息。

 

 

由此,我想到了以下案例。

 

SCN TransactionA(TRAN:A) TransactionB(TRAN:B)   Other Transactions
10 update TabA
20 commit;
:
110 select … from TabA
120 :
130 :
140 : select执行中 大部分的更新、commit
:

 

150             ORA‐1555

 

TRAN:A在执行搜索之前,TRAN:B对成为搜索对象的表进行更新。这时TRAN:A只要读取TRAN:B执行的变更就行了,但在以下的脚本中会发生ORA-1555

 

  1. TRAN:B执行了commit,但对于更新对象的TabA上的块(BL:1)不会记录commit信息。BL:1上中是还没确定(commit)TRAN:B的更新的状态。

 

2. 之后,SCN:110中,TRAN:A开始了对TabA的搜索。但是,这时对于BL:1没有执行block clean up.。(换言之,在BL:1上,TRAN:B的更新还是没有被确定(commit)的状态)

 

  1. TRAN:A开始搜索TabA之后,直到对BL:1执行block clean up之间,除TRAN:A、B以外,大部分事务都会被执行。这些事务中,使用与TRAN:B相同的RBS,TRAN:B为了更新TabA所使用的信息就会被覆盖。

 

  • TRAN:A读入BL:1。BL:1中,TRAN:B执行的更新没有被commit的状态中残留着。 TRAN:A为了读取一致性,需要确定TRAN:B的状态。如果TRAN:B因为比SCN:110更早commit的话就会读入TRAN:B的内容,SCN:110以后commit的话,就不得不读入TRAN:B变更前的before image。

 

  1. TRAN:A为了确认TRAN:B的状态而残留在BL:1中的。TRAN:B将使用过的RBS的信息为基础参考RBS。但是,像3一样,TRAN:B的信息因为其他的大部分事务都已经被执行了,所以就会被覆盖。

 

  1. TRAN:B使用过的RBS信息,被其他事务覆盖了就是TRAN:B自身完结了。但是因为关于TRAN:B所有信息都已经被覆盖了,就无法获得对TRAN:B执行commit的正确的SCN。
  1. TRAN:AはTRAN:Bがコミットを行った正確なSCNを確認するために、TRAN:Bが使用していたRBSのトランザクション・テーブル自体に加えられた変更をロールバックしていき、TRAN:Bがコミットを行ったSCNがSCN:110より前か後かを確認しようとします。これはトランザクション・テーブルに加えられた変更も、UNDOブロックに記録されているからです。

 

  1. 对TRAN:B所使用的RBS的事务表自身的变更,最终事务表的回滚中所需要的UNDO块会被覆盖,TRAN:B commit过的SCN以及SCN:110的大小关系无法确定时,就会发生ORA-1555。

 

  1. 如果,回滚事务表时,TRAN:B中存在使用过的线程以及使用同样线程的事务的话,直到那个事务在SCN:110中被commit的为止,为了使得SCN:110>事务>TRAN:B这样的关系式成立,需要确定TRAN:B直到SCN:110为止被确定。

 

这时,因为无法发现必需的UNDO块时,就会发生ORA-1555。

 

另外,必要的UNDO块就是指检查开始后制成的项目。换言之,直到SCN:110之前,事务都无法回滚,所以也就无法决定TRAN:B以及SCN:110之间的大小关系,就会发生ORA-1555。

 

另外,这些案例中,更新BL:1后,首先读入的是TRAN:A,除TRAN:A以外的事务,在读入BL:1时也会发生同样的现象。读入完成的事务字执行block clean out时,前述的步骤5、6中,不知道正确的commit SCN的话,之后TRAN:A读入BL:1时,沿着前述的步骤进行,commit了 TRAN:B的SCN以及自身所搜索中所使用的与SCN:110之间的大小关系就无法判断,请考虑是否发生了ORA-1555。

 

 

(对应方法3)

 

这个案例中,以下三个要素就是问题的原因。

 

  1. TRAN:A的搜索之前,不执行block clean out。

 

  1. TRAN:A的搜索执行中,为了执行多数事务,TRAN:B使用过的事务表就会被覆盖。

 

  1. 在覆盖TRAN:B的事务表时,就会失去UNDO块信息的覆盖或者开放。

 

因此,对应方法如下所示。

 

  1. Tab:A被再次更新前,执行搜索处理。

 

  1. 发生了ORA‐1555的搜索处理在执行前,通常会执行block clean out。对表只要执行block clean out就够了,但对于索引块,也需要执行block clean out。

 

表的block clean out:

 

SQL> SELECT /*+ FULL(表名) */ COUNT(*) FROM 表名;

 

索引的block clean out:

 

  • 制成B‐Tree索引时

 

SQL> SELECT /*+ INDEX(表名索引名) */ COUNT(*) FROM 表名

 

2 > WHERE 索引列 IS NOT NULL;

 

  • 符合索引时,作为搜索对象列,指定所有的索引列。WHERE语句的条件是符合索引的头列IS NOT NULL 。

 

  • 制成bit map时

 

SQL> SELECT /*+ INDEX(表名 索引名) */ count(*) FROM 表名

 

  1. 为了缩短发生ORA‐1555的搜索处理,就会重新审视搜索语句的调优以及应用。

 

  1. 抑制事务表被覆盖的可能性

 

  • 不执行commit或者减少commit的次数

 

  • Oracle8i 以前,UNDO_MANAGEMENT=MANUAL 的情况

 

  • 增加RBS的数量

 

  • 指定了TranB相应的处理时,另外准备为了执行TranB的回滚段,终止后使其offline。

 

具体来说

  1. TranB开始前,将回滚段(以后是R1)进行offline

 

  1. 用SET TRANSACTION USE ROLLBACK SEGMENT 语句进行明确地指定,或者将其他的回滚段进行offline,使得TranB使用回滚段R1

 

  1. TranB处理完成后,必要的话,在进行shrink之后,将回滚段R1进行offline。

 

  1. 中offline过的回滚段再进行offline

 

  1. 防止UNDO块被覆盖,

 

Oracle9i 之后 UNDO_MANAGEMENT=AUTO时

 

  • 增加初始化参数 UNDO_RETENTION 的值

 

  • 增加undo表区域的尺寸

 

Oracle8i 以前、UNDO_MANAGEMENT=MANUAL 时

 

  • 增加RBS的数量、尺寸

 

  • 重新准备较大的RBS,在TRAN:B中明确地分割较大的RBS

(使用SET TRANSACTION ROLLBACK SEGMENT …)

 

  • 设定了OPTIMAL时,扩大其设定

 

  • 0.1以后,直接加载或者直接插入中的变更,上述方法中,就不会被clean。这是为了提高搜索性能的变更。

 

因此,TranB在直接加载中,用相应的案例,作为对应方法,不会采用2.以外的方法。

 

(原因4) LOB段中发生了ORA-1555的案例

 

LOB列被储存在LOB段中时,对于LOB列追加的变更的UNDO信息不会写入到RBS中,会在LOB段中执行处理。

 

具体而言,执行更新时,获得新的块,在此写入变更后的的LOB数据。变更前的LOB数据就此保留,执行回滚时会被再次使用。Commit之后,变更前的LOB数据就此留存。读取一致性就会被使用。变更前的LOB数据会以可以被覆盖的状态留存,需要新建块时,就会使用旧的项目。为了读取一致性,需要的数据被覆盖了消失时,就会发生ORA-1555。

 

 

 

  • 内嵌LOB,换言之,LOB列与原来的表储存在同一段中时

 

  • UNDO信息与一般的案例同样地被写入到RBS中,所以原因和1-3一样。

 

  • 案例中发生了ORA-1555 。

 

这时典型的案例如下所示。

 

# TabA的列c1作为LOB列。
SCN TransactionA(TRAN:A) TransactionB(TRAN:B)   Other Transactions
10 select c1 from TabA
20 : update TabA.c1
30 : commit
40 : select执行中 更新大部分TabA.c1
:
  • ORA‐1555

 

  1. TRAN:A开始了需要SCN:10的时点的c1的数据的搜索

 

  1. TRAN:B变更需要TRAN:A的行的c1列的值,进行commit。这时,更新前的列值还残留在LOB段上。

 

  1. 更新其他的c1列的事务,更新前的数据就会被覆盖。

 

  1. TRAN:A不会读取更新前的数据,就会发生ORA-1555.

 

这个案例中,伴随着以下的错误信息,ORA-1555中不会记录RBS的编号以及名称。请注意ORA-22924是否有同时发生。

 

SQL> select c2 from t1;

 

ERROR:

 

ORA‐01555: snapshot too old: rollback segment number with name “” too small ORA‐22924: snapshot too old

 

(对应方法4)

 

这个案例中,原因如下所示。

 

  1. TRAN:A的搜索在执行中,会对LOB列执行大部分更新处理

 

  1. TRAN:B更新前的数据就会被覆盖

 

因此,对应方法如下所示

 

  1. 为了不同时进行搜索与更新,需要重新审视应用

 

  1. 为了防止更新前的数据所残留的LOB段被覆盖,需要扩大LOB段PCTVERSION值

 

LOB列PCTVERSION值可以通过以下SQL来确认

 

SQL> select pctversion from user_lobs

 

  • where table_name='<表名>’ and column_name='<列名>’;

 

PCTVERSION

 

‐‐‐‐‐‐‐‐‐‐

10

 

PCTVERSION的值可以通过以下SQL来变更

 

SQL> alter table <表名> modify lob ( <列名> ) (pctversion <新建PCTVERSION值>);

 

 

 

(原因5)

 

使用READ ONLY事务的案例

 

Oracle的READ ONLY事务,读入在事务开始后的数据。执行这样水平的读取一致性。一般的READ WRITE事务中,因为是SQL语句单位的读取一致性,需要读入比那更旧时点的数据。因此,比起一般的READ WRITE事务就更容易发生ORA‐1555。如果获得(原因1)的案例的话

 

SCN TransactionA(TRAN:A) TransactionB(TRAN:B)   Other
10 set transasction read only;
20 update TabA
30 commit
40 大部分更新、commit
  • select from TabA

 

  1. SCN:10中TRAN:A开始了READ ONLY事务

 

  1. 根据TRAN:B对TabA进行更新、commit变更。

 

  1. 由于大部分的事务,TRAN:B使用过的UNDO块就会被覆盖
  2. TRAN:A对TabA执行搜索。TRAN:A在SCN:10时需要TabA的数据。

 

  1. TabA由于TRAN:B来执行更新,所以TRAN:A利用TRAN:B所使用的UNDO块来制成before image,因为UNDO块已经被覆盖了,所以就会发生ORA-1555。

 

READ ONLY事务的案例中,执行与至此不同的搜索语句的更新时,不需要commit。所以就容易发生ORA-1555。

 

(对应方法5)

 

这个案例的情况的原因如下所示。

 

  1. TRAN:A使用READ ONLY事务

 

  1. 在READ ONLY事务执行中, READ ONLY事务会执行成为搜索对象的表的更新

 

因此,对应方法如下所示

 

  1. 不使用READ ONLY事务

 

  1. 在READ ONLY事务执行中,不执行READ ONLY事务的更新

 

(原因6) RBS被删除或者被破坏

 

至此介绍过的例子中,执行RBS的参考时,请考虑RBS被drop rollback segment删除的情况。这时,因为无法参考RBS的内容,就会发生ORA-1555。但是,为了知道事务的正确commit时刻,参考RBS时,因为删除了RBS时的SCN会残留在数据库上,至少在那个事务中事务执行了commit。

 

另外,RBS发生了块故障的情况中,因为无法参考RBS的内容,所以可能发生ORA-155(展示块故障的错误)。

 

(对应方法6)

 

被块故障、media故障破坏的案例中,因为重新执行还是会发生ORA-1555,首先需要执行故障恢复。因为RBS被删除了,所以在发生ORA-1555的案例中,请尽可能减少删除RBS。

 

 

 

(原因7)

 

使用数据库链接的案例

 

在使用数据库链接的分散事务中,可能会发生比访问单个数据库时更复杂的问题。着是因为通过数据库链接来连接的数据库中各自由不同的SCN来管理的。

 

详细内容请参考Document 1744230.1

 

比如,Materialized views刷新时,可能发生预料之外的ORA-1555。详细内容请参考

Document 1731156.1(KROWN:99762) をご参照下さい

 

 

 

[获得信息]

 

作出上述调查以及对策之后还是无法抑制发生ORA-1555的话,请将至此的调查结果。发生错误的应用处理内容、发生错误时所执行的其他的事务信息、以及发生ORA-1555时的错误信息,上传到新建的TAR中。

 

 

Comment

*

沪ICP备14014813号-2

沪公网安备 31010802001379号