延迟块清除和ORA-01555快照过旧

来源:互联网 发布:淘宝店铺发布宝贝草稿 编辑:程序博客网 时间:2024/05/02 00:00

ORA-01555 快照过旧,是数据库中很常见的一个错误,比如当我们的事务需要使用undo来构建CR块的时候,而此时对应的undo 已经不存在了, 这个时候就会报ORA-01555的错误。

ORA-01555错误在Oracle 8i及之前的版本最多。从9i开始的undo自动管理,至现在的10g、11g中的undo auto tuning,使得ORA-01555的错误越来越少。但是这个错误,仍然不可避免。


1. 出现ORA-01555错误,通常有2种情况:

(1)SQL语句执行时间太长,或者UNDO表空间过小,或者事务量过大,或者过于频繁的提交,导致执行SQL过程中进行一致性读时,SQL执行后修改的前镜像(即UNDO数据)在UNDO表空间中已经被覆盖,不能构造一致性读块(CR blocks)。  这种情况最多。

(2)SQL语句执行过程中,访问到的块,在进行延迟块清除时,不能确定该块的事务提交时间与SQL执行开始时间的先后次序。 这种情况很少。


2. 第1种情况解决的办法:

(1)增加UNDO表空间大小

(2)增加undo_retention 时间,默认只有15分钟

(3)优化出错的SQL,减少查询的时间,首选方法

(4)避免频繁的提交


3. 第二种情况描述

块清除就是删除所修改数据块上与”锁定”有关的信息,即事务信息

Oracle在事务相关的提交列表中,记录下已修改的块列表,每个列表记录20个块,根据需要可能分配有多个这种列表.
这种块列表有一个上限,就是缓冲区缓存大小的10%.
如果一次修改的块,没有超过了缓冲区缓存大小的10%,并且这些块在内存中,则commit时,会清除块上的事务信息,
否则,就不会理会它,直到下次访问这些块时,再清除块中的事务信息,这就是延迟块清除.
因为这个Select修改了块的事务信息,所以就会产生Redo.

下面是根据ITPUB上的资料和我的理解整理的关于块清除时SCN的填写,以及什么情况产生”快照太旧”的错误.
延迟清除的块的下一个读者,首先根据块中的记录的回滚信息去查找回滚段中记录的commit时的SCN,如果能找到,那么正常清除,会产生redo log,这也是select会产生redo的原因。
但回滚段可能已回绕,找不到提交时的scn了,
但是,从回滚段事务slot中可以得到一个最小的提交scn并且需要清理的事务已经提交肯定小于这个从回滚段中还存在的最小scn,这是因为事务slot是循环使用的,既然已经回绕,那说明当前slot中最小SCN大于需要清理的事务的SCN。
对于回滚段已回绕的情况,即transaction slot中的最小提交SCN大于待清理事务的SCN,有以下两种可能:

如果select 时的scn 大于回滚段事务slot中最小的scn, 也即select时间点在需要清理的事务提交之后,oracle会给这个块清除的事务分配一个从回滚段中找到的最小事务scn,从而完成块的清除.。这虽然不准确,但是是安全的,对于数据访问也不构成影响。所以叫 upper bound ,猜测的一个scn的上限。

如果select 的scn 比这个回滚段事务slot里面最小的scn 还要小的话,那么oracle需要构造select那个scn的一致块,如果回滚段事务slot已回绕,在回滚段里面找不到数据了,oracle 无法构造一致性块,于是ora-01555就出现了,这个时候oracle 就不知道数据块里面的数据是不是是查询时刻需要的数据.

对于这个理解可以参看metalink文档:

ORA-01555 “Snapshot too old” – Detailed Explanation [ID 40689.1]


老熊blog上关于defered Clean的场景说明:

(1)有事务大量修改了A表的数据,或者A表的数据虽然被事务少量修改,但是一部分修改过的块已经刷出内存并写到了磁盘上。随即事务提交,提交时刻为SCN1。而提交时有数据块上的事务没有被清除。

(2)在SCN2时刻,开始执行SELECT查询A表,对A表进行全表扫描,而且A表很大。也可能是其他情况,比如是小表,但是是一个游标方式的处理过程,而处理过程中又非常耗时。注意,这里SCN2与SCN1之间可能相隔了很远,从时间上来说,甚至可能有数十天。不管怎么样,这在SCN1至SCN2时间之间,系统中存在大量的事务,使得UNDO表空间的块以及UNDO段头的事务表全部被重用过。

(3)SELECT语句在读A表的一个块时,发现表上有活动事务,这是由于之前的事务没有清除所致。ORACLE根据数据块中ITL的XID检查事务表,这时会有2种情况:

(A)XID对应的事务表中的记录仍然存在并发现事务已经提交,可以得到事务准确的提交SCN(commit scn),称为SCN3,等于SCN1。很显然,由于查询的时刻SCN2晚于事务提交的时刻SCN1,那么不需要构造一致性读块。

(B)XID对应的事务表中的记录已经被重用,这个时候仍然表明表明事务已经被提交。那么这个时候,Oracle没办法准确地知道事务的提交时间,只能记录为这样一个事实,事务提交的SCN小于其UNDO段的事务表中最近一次重用的事务记录的SCN(即这个事务表最老的事务SCN)。这里称这个SCN为SCN4。

(4)SCN4可能远小于SCN2,那是因为事务很早之前就已经提交。也可能SCN4大于SCN2,这是因为SELECT语句执行时间很长,同时又有大量的事务已经将事务表重用。对于后者,很显然,Oracle会认为该事务的提交时间可能在SELECT开始执行之后。这里为什么说可能,是因为ORACLE只能判断出事务是在SCN4之前提交的,并不是就刚好在SCN4提交。而此时,利用UNDO BLOCK进行一致性读数据的构造也很可能失败,因为UNDO BLOCK很可能已经被覆盖,特别是SCN1远小于SCN2的情况下。

在这种情况下,ORA-01555错误就会出现。

对这种由于表上存在未清除的事务,同时导出时间过长,UNDO段头的事务表被全部重用,ORACLE在查询到有未清除事务的块时不能确定事务提交时间是否早于导出(查询)开始时间,报ORA-01555错误。


来源1:http://www.cuug.com/xueyuanzhuanqu/jishuwenzhang/201302/jishuwenzhang-2208.html

来源2:http://www.dbasky.com/oracle/delayed_block_cleanout_ora_01555.html


0 0
原创粉丝点击