一、引言:
[oracle@yft yft]$ oerr ora 01555
01555, 00000, "snapshot too old: rollback segment number %s with name "%s" too small"
// *Cause: rollback records needed by a reader for consistent read are
// overwritten by other writers
// *Action: If in Automatic Undo Management mode, increase undo_retention
// setting. Otherwise, use larger rollback segments
ORA-01555 快照过旧,是数据库中很常见的一个错误,比如当我们的事务需要使用undo来构建CR块的时候,而此时对应的undo已经不存在了,这个时候就会报ORA-01555的错误。
ORA-01555错误在Oracle 8i及之前的版本最多。从9i开始的undo自动管理,至现在的10g、11g中的undo auto tuning,使得ORA-01555的错误越来越少。但是这个错误,仍然不可避免。
二、出现ORA-01555错误,通常有2中情况:
(1)、SQL语句执行时间太长,或者undo表空间过小,或者事务量过大,或者过于频繁的提交,导致执行SQL过程中进行一致性读时,SQL执行后修改的前镜像(既UNDO数据)在UNDO表空间中已经被覆盖,不能构造一致性读块(CR blocks)。这种情况最多。
(2)、SQL语句执行过程中,访问到的块,在进行延迟块清除时,不能确定该块的事务提交时间与SQL执行开始时间的先后次序。这种情况很少。
三、模拟ORA-01555场景:
1 SQL> create table jack (id int,name varchar2(10));
2
3 Table created.
4
5 SQL> insert into jack values(1,'a');
6
7 1 row created.
8
9 SQL> insert into jack values(2,'b');
10
11 1 row created.
12
13 SQL> commit;
14
15 Commit complete.
16
17 SQL> show parameter undo
18
19 NAME TYPE VALUE
20 -------------------- ----------- --------------
21 undo_management string AUTO
22 undo_retention integer 900
23 undo_tablespace string UNDO2
24 SQL> create undo tablespace undo1 datafile '/u01/app/oracle/oradata/yft/undo01.dbf' size 1m;
25
26 Tablespace created.
27
28 SQL> alter system set undo_retention=1;
29
30 System altered.
31
32 SQL> var x refcursor
33 SQL> begin
34 2 open :x for select * from jack;
35 3 end;
36 4 /
37
38 PL/SQL procedure successfully completed.
39
40 SQL> begin
41 2 for i in 1 .. 20000 loop
42 3 update jack set id=id+1;
43 4 commit;
44 5 end loop;
45 6 end;
46 7 /
47
48 PL/SQL procedure successfully completed.
49
50 SQL> print :x
51 ERROR:
52 ORA-01555: snapshot too old: rollback segment number 17 with name
53 "_SYSSMU17_2039231318$" too small
54
55
56
57 no rows selected
四、第1种情况解决的办法:
(1)、增加UNDO表空间大小;
(2)、增加undo_retention时间,默认只有15分钟;
(3)、优化出错的SQL,减少查询的时间,首选方法;
(4)、避免频繁的提交。