一、引言:
[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)、避免頻繁的提交。