下面这段代码是在《expert one on one》上看到的,每太看明白,请高手指点下:tkyte@TKYTE816> create table t as select * from all_objects;
Table created.tkyte@TKYTE816> create index t_idx on t(object_name);
Index created.tkyte@TKYTE816> create rollback segment rbs_small storage (initial 64k
2 next 64k minextents 2 maxextents 4 ) tablespace tools;
Rollback segment created.tkyte@TKYTE816> begin
2 for x in ( select rowid rid, object_name, rownum r
3 from t
4 where object_name > chr(0) )
5 loop
6 update t
7 set object_name = lower(x.object_name)
8 where rowid = x.rid;
9 if ( mod(x.r,100) = 0 ) then
10 commit;
11 end if;
12 end loop;
13 commit;
14 end;
15 /
begin
*
ERROR at line 1:
ORA‐01555: snapshot too old: rollback segment number 10 with name ʺRBS_SMALLʺ too
small
ORA‐06512: at line 2
1. 哪条语句导致的ORA‐01555错误?
2. 什么信息snapshot too old了?怎么导致的?小弟刚刚问过一遍,自己也很晕,估计问的不太明白,重新整理下问题,希望各位高手给分析下

解决方案 »

  1.   

    snapshot too old 这个错误一搜就明白了。一般是undo表空间中的数据被覆盖引起的读写不一致引起的rollback segment 回滚段太小
      

  2.   

    create rollback segment rbs_small storage (initial 64k
     next 64k minextents 2 maxextents 4 ) tablespace tools;
    这个句创建了一个非常小的回滚段
    所以update的时候回滚段会因为不足而报错
      

  3.   

    是ORA‐01555错误,不是回滚段不足错误
      

  4.   

    ORA‐01555: snapshot too old: rollback segment number 10 with name ʺRBS_SMALLʺ too
    small
    报错挺明确的吧
      

  5.   

    1.第一步创建一个很小的回滚段
    2.打开一个cursor
    3.第三步对cursor中的记录进行update,100条commit一次.
    因为回滚段很小,很快回滚段就会被用完,然后将会重用已经被commit记录占用的回滚段,这样从cursor提取记录的时候,cursor发现已经无法保证能读取到cursor打开时的数据,所以会报错snapshot too old.也就是被放到回滚段的snapshot(快照)因为被重用已经不存在了.
      

  6.   

    commit那步很重要,如果没有这步会直接报ora-01545回滚段不足.
    但是总归最终原因是回滚段不足.