快照過期

當執行一個查詢時間非常長的時候,可能碰到ora-01555錯誤,本文來模擬並解釋一下原因.

013555是因爲查詢的數據在執行查詢的過程中,被修改了,同時在undo表空間中已經找不到了造成的.

首先來了解一下Oracle在執行一個查詢的時候,在開始查詢後其根據條件本該查詢出來的數據發生變化的時候,Oracle是將變化之前的數據查詢出來的.模擬如下:

1,有一張表的數據如下:

SQL> select *  from A;
        ID VAL
---------- ----------
         1 a
         2 b

2,在一個session(session A)中通過遊標查詢不open的方式模擬查詢開始了,但是還沒有真正訪問某一條記錄:

SQL> variable rc refcursor;
SQL> exec open :rc for select * from A;  --這時候只是表示了開始查詢,記錄了查詢開始的SCN信息等

PL/SQL procedure successfully completed.

3,在另一個session(session B)中修改A表的數據如下並且提交:

SQL> update A set val = 'C';
2 rows updated.
SQL> commit;
Commit complete.

4,在session A中開始訪問已經修改並且提交的數據,但是看的數據仍然是查詢開始的時間點的數據:

SQL> print rc;
        ID VAL
---------- ----------
         1 a
         2 b

上面的過程是Oracle通過undo表空間中的數據保證的.

那麼如果在print rc的時候,undo表空間中對應查詢開始時間點的數據不存在了的話,就會01555了.

1,爲了模擬這個現象,我們需要讓系統使用一個比較小的undo表空間,並且不自動擴展.

create undo tablespace undotbs02 datafile 'D:\ORACLE\PRODUCT\10.2.0\ORADATA\ORCL\UNDOTBS02.DBF' size 1M;
alter system set undo_tablespace=undotbs02

2,在一個session(session A)中通過遊標查詢不open的方式模擬查詢開始了,但是還沒有真正訪問某一條記錄:

SQL> variable rc refcursor;
SQL> exec open :rc for select * from A;  --這時候只是表示了開始查詢,記錄了查詢開始的SCN信息等

PL/SQL procedure successfully completed.

3,在另一個session(session B)中修改A表的數據如下並且提交,通過下面的循環修改造成undo表空間的數據被覆蓋:
SQL> declare
  2  i number :=0;
  3  begin
  4  loop
  5  update a set id=i;
  6  i := i+1;
  7  if mod(i,200)=0 then
  8  commit;
  9  end if;
 10  end loop;
 11  end;
 12  /

4,在session A中開始訪問已經修改並且提交的數據,發生01555錯誤

SQL> print rc;
ERROR:
ORA-01555: snapshot too old: rollback segment number 16 with name "_SYSSMU16$"
too small


*最好在執行循環更新的那個session中開始的時候通過 select distinct sid from v$mystat;把sid記下來,最後通過alter system kill session '$sid,$serial#' 殺死那個session,
如果萬一沒有最先記錄下來也可以通過select * from v$locked_object看出那個循環更新的session.



另外,改變了但是沒有提交的數據是必須放在undo表空間的,如果undo表空間不夠用,會發生ORA-30036錯誤.還是在undo表空間只有1M的情況下做下面的實驗:

SQL> select count(*) from A;

  COUNT(*)
----------
     20008

SQL> delete from A;
delete from A
            *
ERROR at line 1:
ORA-30036: unable to extend segment by 8 in undo tablespace 'UNDOTBS02'

將undo表空間改爲一個有比較大的size的datafile的表空間則可以正常delete.
--------------------- 
作者:IT農夫 
來源:CSDN 
原文:https://blog.csdn.net/kkdelta/article/details/7635430 
版權聲明:本文爲博主原創文章,轉載請附上博文鏈接!

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章