回滾段概述
回滾段用於存放數據修改以前的值(包括數據修改以前的位置和值)。回滾段的頭部包含正在使用的該回滾段事務的信息。一個事務只能使用一個回滾段來存放它的回滾信息,而一個回滾段能夠存放多個事務的回滾信息。
回滾段的做用
事務回滾:當事務修改表中數據的時候,該數據修改前的值(即前影像)會存放在回滾段中,當用戶回滾事務(ROLLBACK)時,ORACLE將會利用回滾段中的數據前影像來將修改的數據恢復到原來的值。
事務恢復:當事務正在處理的時候,例程失敗,回滾段的信息保存在重作日誌文件中,ORACLE將在下次打開數據庫時利用回滾來恢復未提交的數據。
讀一致性:當一個會話正在修改數據時,其餘的會話將看不到該會話未提交的修改。並且,當一個語句正在執行時,該語句將看不到從該語句開始執行後的未提交的修改(語句級讀一致性)。當ORACLE執行SELECT語句時,ORACLE依照當前的系統改變號(SYSTEM CHANGE NUMBER-SCN)來保證任何前於當前SCN的未提交的改變不被該語句處理。能夠想象:當一個長時間的查詢正在執行時,若其餘會話改變了該查詢要查詢的某個數據塊,ORACLE將利用回滾段的數據前影像來構造一個讀一致性視圖。 sql
回滾段的類型數據庫
回滾段可分爲系統回滾段和非系統回滾段, 其中非系統回滾段又分爲PUBLIC回滾段和PRIVATE回滾段。緩存
回滾段:1 系統回滾段session
2 非系統回滾段:(1)PUBLIC回滾段併發
(2)PRIVATE回滾段oracle
系統回滾段用於處理涉及系統的CATALOG的事物(好比大多數的DDL), 它位於SYSTEM表空間, 因爲只有SYSTEM表空間能夠隨時保持可用, 所以,不要把SYSTEM回滾段放在其餘的表空間中.app
原則1: 系統回滾段應放在SYSTEM表空間中, 而且應該永遠保持ONLINE狀態.oop
PUBLIC回滾段對於數據庫的全部實例(INSTANCE)都是可用的, 除非將其顯式設置爲OFFLINE.性能
PRIVATE回滾段是指對於數據庫的某個實例是私有的, 爲了使用PRIVATE回滾段, 某個實例應當在其INITsid.ORA的ROLLBACK_SEGMENTS中標明全部要使用的PRIVATE回滾段, 或經過使用ALTER ROLLBACK SEGMENT XXX ONLINE來使用某一個回滾段.測試
建議1: 在單實例系統中,建議將全部回滾段設爲PUBLIC.
建議2: 在多實例系統中(如OPS,RAC), 建議將每一個實例的PRIVATE回滾段放置到訪問比較快的本地設備上.
回滾段的數量規劃
對於OLTP系統,存在大量的小事務處理,通常建議:
數量多的小回滾段;每四個事務一個回滾段;每一個回滾段不要超過十個事務。
對於批處理,通常建議:
少的大回滾段;每一個事務一個回滾段。
回滾段的使用
分配回滾段:當事務開始時,ORACLE將爲該事務分配回滾段,並將擁有最少事務的回滾段分配給該事務。事務能夠用如下語句申請指定的回滾段:
SET TRANSTRACTION USE ROLLBACK SEGMENT rollback_segment
事務將以順序,循環的方式使用回滾段的區(EXTENTS),噹噹前區用滿後移到下一個區。幾個事務能夠寫在回滾段的同一個區,但每一個回滾段的塊只能包含一個事務的信息。
例如(兩個事務使用同一個回滾段,該回滾段有四個區):
一、事務在進行中,它們正在使用回滾段的第三個區;
二、當兩個事務產生更多的回滾信息,它們將繼續使用第三個區;
三、當第三個區滿後,事務將寫到第四個區,當事務開始寫到一個新的區時,稱爲翻轉(WRAP);
四、當第四個區用滿時,若是第一個區是空閒或非活動(使用該區的全部事務完成而沒有活動的事務)的,事務將接着使用第一個區。
回滾段的查詢
1 查詢數據庫的的回滾段狀況
select owner,segment_id,segment_name,tablespace_name,status from dba_rollback_segs;
2 查看系統回滾段基本信息
select segment_name,tablespace_name,bytes,next_extent from dba_segments where segment_type='ROLLBACK';
從上面僅僅是查詢到回滾段的基本信息,要了目前各個回滾段的動態信息,還要查詢V$ROLLNAME和V$ROLLSTAT視圖。V$ROLLNAME視圖只存放各回滾段的編號和名字,V$ROLLSTATS存放各個回滾段當前的狀況信息。要想獲得每一個回滾段的信息,就要查詢兩個表的信息才能獲得。如:
select s.usn,n.name,s.extents,s.optsize,s.hwmsize,s.status from v$rollstat s, v$rollname n where s.usn=n.usn
2 查看回滾段的使用狀況,哪一個用戶正在使用回滾段的資源(當提交或回滾後資源釋放):
SELECT s.username, u.name FROM v$transaction t, v$rollstat r, v$rollname u, v$session s WHERE s.taddr = t.addr AND t.xidusn = r.usn AND r.usn = u.usn ORDER BY s.username;
3 回滾段當前活動的事物(事務提交或回滾後自動清空)
SELECT s.username,t.xidusn,t.ubafil,t.ubablk,t.used_ublk FROM v$session s,v$transaction t;
4 分析 UNDO 的使用狀況
SELECT TABLESPACE_NAME,STATUS,TRUNC(SUM(BLOCKS) * 8 / 1024) AS "Size M",COUNT(*) Undo_Extent_Num FROM DBA_UNDO_EXTENTS GROUP BY TABLESPACE_NAME, STATUS;
5 監控undo表空間
SELECT BEGIN_TIME, END_TIME, UNDOTSN, UNDOBLKS, TXNCOUNT,MAXCONCURRENCY AS "MAXCON" FROM V$UNDOSTAT;
6 查詢是否有回滾段的爭用
select * from v$waitstat;
SELECT name, waits, gets, waits/gets "Ratio" FROM v$rollstat a, v$rollname b WHERE a.usn = b.usn;
7 查看回滾段的統計信息:
SELECT n.name, s.extents, s.rssize, s.optsize, s.hwmsize, s.xacts, s.status FROM v$rollname n, v$rollstat s WHERE n.usn = s.usn;
8 查詢回滾段的事務回退率
transaction rollbacks/(transaction rollbacks+user commits)
select name,value from v$sysstat where name in('user commits','transaction rollbacks');
9 查詢回滾段在使用,擴展,回縮的時候extent在循環的次數
select usn,wraps from v$rollstat;
10 查詢回滾段收縮的狀況
select usn,optsize,shrinks from v$rollstat;
建立回滾段
語法:
CREATE [PUBLIC] ROLLBACK SEGMENT rollback_segment
[TABLESPACE tablespace]
[STORAGE ([INITIAL integer[K|M]] [NEXT integer[K|M]]
[MINEXTENTS integer]
[MAXTENTS {integer|UNLIMITED}]
[OPTIMAL {integer[K|M]|NULL}]) ]
注:
回滾段能夠在建立時指明PRIVATE或PUBLIC,一旦建立將不能修改。
MINEXTENTS 必須大於等於2
PCTINCREASE必須是0
OPTIMAL若是要指定,必須大於等於回滾段的初始大小(由MINEXTENTS指定)
建議:
通常狀況下,INITIAL=NEXT
設置OPTIMAL參數來節約空間的使用
不要設置MAXEXTENTS爲UNLIMITED
回滾段應建立在一個特定的回滾段表空間內
參數的意義同建表上樣,但這裏不容許使用pctincrease參數,所以其增漲百分比老是零。這裏的參數的使用(執行效果)與表的參數有很大的不一樣。一表中的數據在關機後仍放於該表空間所對應的數據文件中,而回滾段只在系統運行且在insert , update , delete時用,後便可釋放(讓別的transaction用),且在關機後所記錄的全部回滾信息均被釋放,於是就有擴展後的空間如何釋放的問題,即保持多少空間爲最佳的問題(由OPTIMAL)設定。Optimal能夠避免「snapshot too old」錯誤的發生,爲每一個rollback segmal指定一個optimal以便在內存中保持一個較少的cache值,從而提升性能。
例:
create tablespace rbs datafile '/data/oradata/cts/rbs01.dbf' size 100M autoextend on next 10M maxsize 150M;
create public rollback segment rbs01 tablespace rbs storage(initial 100K next 100K minextents 10 maxextents 100 optimal 1000K);
select segment_name,tablespace_name,status from dba_rollback_segs ;
可是:建立成功後也查詢不到,由於從9i開始,回滾段開始自動管理,不須要手動建立
SQL> show parameter undo
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
undo_management string AUTO
undo_retention integer 900
undo_tablespace string UNDOTBS1
若是想改回手動管理須要執行一下操做:
ALTER SYSTEM SET UNDO_MANAGEMENT=MANUAL SCOPE=SPFILE
Alter system set undo_management=MANUAL scope=spfile;
shutdown immediate
startup
select segment_name,owner,status from dba_rollback_segs;
改變回滾段
當回滾段創建好了以後,有時須要對它們進行修改。能夠對回滾段進行存儲參數的修改,能夠對某個脫機(OFFLINE)回滾段修改成聯機(ONLINE)。也可能對已經處於聯機的回滾段設置爲脫機,好比當咱們進行IMP或大量修改數據時,ORACLE老是須要大的回滾段。但因爲分配回滾段是ORACLE系統包辦。爲了在事務處理中獲得大的回滾段,咱們只能將較小的回滾段設置爲脫機的狀態,等到咱們所處理的事務完成後在將它們設置爲聯機等。
設置實例重啓動後回滾段聯機
除了上面使用CREATE ROLLBACK SEGMENT命令完成回滾段的建立外,要使ORACLE系統關閉從新啓動後仍然處於聯機,還要在initsid.ora 參數文件中rollback_segments參數加上回滾段的名字,如:
rollback_segments= (r0,r1,r2 )
使回滾段在線
當回滾段建立後,回滾段是離線的,不能被數據庫使用,爲了使回滾段被事務利用,必須將回滾段在線。能夠用如下命令使回滾段在線:
ALTER ROLLBACK SEGMENT rollback_segment ONLINE;
例:
ALTER ROLLBACK SEGMENT rbs01 ONLINE;
爲了使回滾段在數據庫啓動時自動在線,能夠在數據庫的參數文件中列出回滾段的名字。例如在參數文件中加入如下一行:
ROLLBACK_SEGMENT=(rbs01,rbs02)
select name,status,gets,waits from v$rollname,v$rollstat where v$rollstat.usn=v$rollname.usn;
回滾段的擴張(EXTEND)
噹噹前回滾段區的全部塊用完而事務還須要更多的回滾空間時,回滾段的指針將移到下一個區。當最後一個區用完,指針將移到第一個區的前面。回滾段指針移到下一個區的前提是下一個區沒有活動的事務,同時指針不能跨區。當下一個區正在使用時,事務將爲回滾段分配一個新的區,這種分配稱爲回滾段的擴展。回滾段將一直擴展到該回滾段區的個數到達回滾段的參數MAXEXTENTS的值時爲止。
回滾段擴展次數的限制
在比較舊的ORACLE版本里,回滾段的擴展次數受到一些限制,它與實例的塊大小有關。好比:
當ORACLE 塊=2k時,maxextents 121
當ORACLE 塊=4k 時,maxextents 249
當ORACLE 塊=8k 時,maxextents 505
當ORACLE 塊=16k 時,maxextents 1017
當ORACLE 塊=32k 時,maxextents 2041
注:在ORACLE V7.3 之後,Maxextents 的擴展次數已被取消,你能夠設得足夠大。甚至能夠設爲 UNLIMITED ( =249 000 000 )。
回滾段的回收和OPTIMAL參數
OPTIMAL參數指明回滾段空閒時收縮到的位置,指明回滾段的OPTIMAL參數能夠減小回滾段空間的浪費。
設置OPTIMAL參數
因爲回滾段是一個動態的對象,它在使用中根據增刪改的數據量而增長(擴展),但在用完後就被釋放,而後另外的事務能夠用。爲了不某個回滾段在擴展後總佔用量的空間,不利於另外的回滾段的擴展,ORACLE 提供了 optimal 參對回滾段進行控制,該參數的意義是回滾段在擴展過程當中,當事務完成後(發commit,rollback後),將回滾段的大小按照optimal 值進性收縮。
須要注意的是,optimal 參數的設置不能比已經分配的空間還小。也就是說,optimal 的設置要比初始的擴展的還大才正確。好比:
通常 optimal = minextents * initial +
( minextents + n ) * next
其中,要求minextents>=1 ; n>= 1
例如:
CREATE ROLLBACK SEGMENT rbs21 tablespace rbs
STORAGE( initial 10m next 2m minextents 2 optimal 16M );
這裏optimal 只能填 14m 或 16m 或18m 等,不能填12m,由於最小擴展爲2次,即rbs21回滾段的開始分配已是 10m + 2m = 12m ,根據optimal 要大於初始值的原則,因此optimal 至少從 14m開始。
例子:
systen回滾段的初始分配initial = 409600 ;
下一次分配 next = 57344;
最佳擴展值 optimal= null;
根據這樣的狀況,咱們能夠修改下一次分配的值爲 1MB(=1024000字節);修改最佳擴展值爲:optimal = initial + 2 * next = 409600 + 2* 1024000 = 2457600 。因此修改SYSTEM回滾的命令爲:
SQL> alter rollback segment system storage(next 1m optimal 2457600);
注:optimal 表示在事務處理當中,該回滾段因爲增、刪、改的數據量的須要而不斷對回滾段進行擴展,以知足事務的要求,可是在事務處理完成後可讓回滾段縮小到一個最佳的範圍內。這就是由回滾段的OPTIMAL參數來控制。通常optimal = initial + n* next , 且 n >1 。
修改回滾段的存儲參數
可使用ALTER ROLLBACK SEGMENT命令修改回滾段的存儲參數(包括OPTIMAL,MAXEXTENTS)。
語法:
ALTER ROLLBACK SEGMENT rollback_segment
[STORAGE ([NEXT integer[K|M]]
[MINEXTENTS integer]
[MAXEXTENTS {integer|UNLIMITED}]
[OPTIMAL {integer[K|M]|NULL}]) ]
例:
ALTER ROLLBACK SEGMENT rbs01 STORAGE (MAXEXTENTS 1000);
回收回滾段的空間
若是指定了回滾段的OPTIMAL參數,ORACLE將自動回收回滾段到OPTIMAL指定的位置。用戶也能夠手動回收回滾段的空間。
語法:
ALTER ROLLBACK SEGMENT rollback_segment SHRINK [TO integer [K|M]];
說明:
若是不指明TO integer的數值,ORACLE將試圖回收到OPTIMAL的位置。
例:
ALTER ROLLBACK SEGMENT rbs01 SHRINK TO 2M;
使回滾段離線
select name,status,gets,waits from v$rollname,v$rollstat where v$rollstat.usn=v$rollname.usn;
爲了達到如下兩個目的將要回滾段離線:
1.阻止新的事務使用該回滾段;
2.該回滾段必須刪除。
語法:
ALTER ROLLBACK SEGMENT rollback_segment OFFLINE;
例:
ALTER ROLLBACK SEGMENT rbs01 OFFLINE;
說明:
若是有事務正在使用該回滾段,運行該命令後,回滾段的狀態將是PENDING OFFLINE。事務結束後,狀態將改成OFFLINE,能夠經過V$ROLLSTAT查詢回滾段的狀態。
觀察回滾段的增加
雖然回滾段在使用過程當中做過擴展而在用完後又自動按照 OPTIMAL 要求大小縮小,但在動態字典V$ROLLSTAT 中會記錄曾經擴展的狀況。命令以下:
select n.name, optsize, hwmsize from v$ROLLNAME n , V$ROLLSTAT s where n.usn=s.usn ;
optsize 是 最優大小值, hwmsize =Hight water mark of rollback segment size 回滾段擴展中最高值(水位)。若是 optsize 爲空,則 hwmsize 就是當前最高值。
增長 ORACLE 系統 rbs 表空間數據文件
alter tablespace rbs add datafile '/disk1/ORACLE/oradata/ora8/rbs02.dbf' size 120m ;
在事務中指定使用回滾段
因爲回滾段創建好了後,在處理中回滾段的使用是由系統安排的,這樣就有可能在處理中實際須要較大的回滾段而系統老是分配較小的回滾而致使處理失敗。爲避免這樣的失敗出現。就要在命令中或程序中用 SET TRANSACTION USE ROLLBACK SEGMENT命令來實現。
須要注意的是,在程序中使用設置命令時,要在程序的開始來使用 SET TRANSACTION 語句,並且在每次的COMMIT或ROLLBACK語句後都要從新使用SET TRANSACTION 語句,若是在COMMIT或ROLLBACK語句後再也不使用SET TRANSACTION 語句,系統會釋放原來被分配的回滾 段而隨機分配新的回滾段。下面給出在SQL下和在PL/SQL下使用回滾段的例子。
在執行大事務時,有時oracle會報出以下的錯誤:
ORA-01555:snapshot too old (rollback segment too small)
這說明oracle給此事務隨機分配的回滾段過小了,這時能夠爲它指定一個足夠大的回滾段,以確保這個事務的成功執行。
set transaction use rollback segment roll_abc;
delete from table_name where ...
commit;
回滾段roll_abc被指定給這個delete事務,commit命令則在事務結束以後取消了回滾段的指定.
1.在SQL>下使用回滾段:
在SQLPLUS下進行任何大量的INSERT、UPDATE和DELETE 都要用到回滾段,如何你但願操做能成功的話,你應該在操做前指定要用大的回滾段。如:
Commit;
Set transaction use rollback segment r1;
Delete from ...
Commit;
Set transaction use rollback segment r1;
例子:爲大事務創建大的回滾段:
create rollback segment interest tablespace interest_tabspace
storage( initial 50m next 10m optimal 80m pct_increase 0 );
肯定回滾段的數目
回滾段的數量直接影響到系統的性能,若是回滾段的個數不夠多,則在多個用戶同時進行增、刪、該時就存在等待現象。
要肯定是否增長回滾段的數量,先要查詢兩個動態視圖,即V$ROLLSTAT,V$WAITSTAT。如:
SQL> select * from v$waitstat where class='undo header';
CLASS COUNT TIME
------------------ ---------- ----------
undo header 0 0
SQL> select usn,extents,waits from v$rollstat;
USN EXTENTS WAITS
---------- ---------- ----------
0 5 0
1 8 0
2 8 0
3 8 0
4 8 0
5 8 0
6 8 0
7 8 0
若是 waits 存在大於 0 的數,則須要增長回滾段的數量。通常回滾段的數量主要根據應用系統的類型來決定。好比通常的歷史檔案系統,因爲其主要處理是查詢。這類增、刪、改相對較少的應用,能夠創建較少的回滾段。而想銀行、證券等應用。就須要不少的回滾段。那麼到底要多少才相對就夠了呢? 下面的回答具備通常性:
在併發程度要求高的應用系統,同一時間內有多個 transaction 在競爭竟爭回退段。假如transaction爲事務的個數;則有:
n= transaction/transactions_per_rollback_segment
其中:
n= 回退段數量
transaction 爲ORACLE 系統參數,系統中容許併發處理的最大transaction 數。
transactions_per_rollback_segment 爲 ORACLE 參數,每一個回退段容許同時寫入的最大 transaction 數。
另外,若是從 v$waitstat 動態視圖中查出自數據庫啓動後回退頭的等待次數較高,則應該多創建回滾段。
建立通用回滾段
不管是任何類型的應用,建議從新創建新的回滾段。除了上面介紹的創建專門的回滾段之外,須要創建初始值,下次增長及最佳值合適的值。通常建議是 初始值 最好是 5MB以上,下次增加爲 2MB至 5MB之間,最佳值在 20M至30MB之間。
刪除已存在的回滾段 r01
當回滾段再也不須要或要重建以改變INITIAL,NEXT或MINEXTENTS參數時,能夠將其刪除。要刪除回滾段,不準使該回滾段離線。
語法:
DROP ROLLBACK SEGMENT rollback_segment;
例:
DROP ROLLBACK SEGMENT rbs01;
查詢回滾段的信息
所用數據字典:DBA_ROLLBACK_SEGS
alter rollback segment r01 offline;
drop rollback segment r01;
回滾段使用量的估算
如何保證有足夠的回滾段,知足多個併發的transaction同時使用,又要考慮應有足夠大的回滾段來知足特殊的transaction(如 long-runing transaction)的須要。這就是如何考慮回滾段的數量和大小的問題。除了system回滾段外,一般還要建立多個回滾段,一般較短的transaction 適於使用較小的回滾段,這將使系統將使系統有較好性能(由於大量的回滾信息可緩存於sga中。從而減小對硬盤的I/O)。而大的transaction則須要使用較大的回滾段,由於大量的回滾信息能夠存入事先分配的extent中避免了動態分配空間;同時也防止transaction運行期間,用盡回滾段的空間後,而致使數據庫出現ora-01562錯誤。
一、 回滾信息量
存儲於回滾段中的回滾信息量取決於transaction (insert, update, delete )類型和實際處理數據量,一般,insert向表中插入一第記錄所產 生的回滾數據小於delele 從表中刪除一條記錄。由於回滾insert所產生的記錄只是需刪除它,而回滾一條刪除記錄須要從新插入該記錄,前者在回滾段中只存儲rowid,後者則存儲了從新這條記錄的全部信息。
2.回滾數據量的估計
到目前爲止,ORACLE不能提供一個很好的回滾段數據量的計算,做爲dba能夠 用下面方法進行估算:
1) 創建一個較小的測試表(數據來自實際表EMP);
create table emp1 as select * from emp where deptno <=10;
2) 模仿(實際updeste 語句)transaction 做以下測試:
update emp1 set deptno=1050 where deptno<=100;
3)利用 v$rollstat
依據以上三步能夠在 SQL> 下進行以下操做,從而得出基本回滾信息量:
SQL>select sum(writes) "begin" from sys.v$rollstat;
SQL>update emp1 set deptno=1000 where deptno <=100;
SQL>select sum(writes)"end" from sys.v$rollstat;
小表的信息量= end - begin = test
實際 transaction 的回滾信息量 = test * (emp_row / emp1_row ) * 1.05
因爲一個 事務 的所有回滾信息能夠寫入多個 extent 中, 但每一個回滾段的 extent 數量受到限制。因此在設置 storage 的 initial , next 參數時要當心, 通常回滾段中的 extent 保持在 10 到 20 爲理想。爲了在 extent 後的空間部分被釋放, 在 STORAGE 中提供 optimal 參數用以控制回滾段的大小。當回滾段須要分配更多的空間超過 optimal 值後, RDBMS 將檢查回滾段的大小,一旦額外分配的extent 中無工做的 事務 且回滾段頭正在指向 extent時,系統將釋放這個 extent 回滾段的大小向回縮, 直至到 optimal 指定值。
回滾段的問題及解決方法
(1)事務要求的回滾段空間不夠,表現爲表空間用滿(ORA-01560錯誤),回滾段擴展到達參數MAXEXTENTS的值(ORA-01628)。
解決方法:
A. 擴大回滾段所在表空間
B. 設置較大的MAXEXTENTS參數
C. 爲回滾段設置OPTIMAL參數
D. 用較大的EXTENT參數從新建立回滾段
向回滾段表空間添加文件或使已有的文件變大;增長MAXEXTENTS的值。
ORA-01562: failed to extend rollback segment number 12
ORA-01628: max # extentsreached for rollback segment RBS12
擴大表空間
給回滾段表空間增長數據文件,並設置大回滾段apprbs的maxextents值爲無限大:
alter tablespace rbs add datafile ‘/opt/oracle/db02/oradata/ORCL/rbs02.dbf‘ size 8192m autoextend on next 10m maxsize unlimited;
擴大參數
ALTER ROLLBACK SEGMENT rbs01 STORAGE (MAXEXTENTS 1000);
可用以下語句代替(批量提交釋放回退段空間):
1
create table tt(id number,sal number,age number);
2
declare
begin
for i in 1..10000 loop
insert into tt values(i,i*10,i*100);
end loop;
end;
select * from tt order by id;
刪除表tt中id不等於10的全部數據
3
begin
loop
delete from tt where id !=10 and rownum<=10;
exit when sql%notfound;
commit;
end loop;
end;
其中rownum<=10的目的是每10條提交一次;
(2) ORA-01552 cannot use system rollback segment for non-system tablespace
'string'
緣由: 沒有可用的非系統回滾段. 分爲如下情形:
A. 除了系統回滾段, 未建立其它回滾段
B. 只建立了PRIVATE回滾段, 但INITsid.ORA的ROLLBACK_SEGMENTS中未列出這些回滾段
C. 建立了PUBLIC回滾段, 但這些回滾段都處於OFFLINE狀態
解決方法: 根據以上緣由相應解決便可
(3) ORA_01555 snapshot too old: rollback segment number string with name "string" too small
緣由可分爲如下情形:
A. 回滾段太少/過小
數據庫中有太多的事務修改數據並提交, 就會發生已提交事務曾使用的空間被重用, 從而形成一個延續時間長的查詢所請求的數據已經不在回滾段中
(即:長查詢開始以前,事務被修改而且沒有提交,長查詢進行中,事務提交,而且事務所在回滾段被其餘事務覆蓋,這時就會出現ora-01555錯誤)
解決方法: 建立更多的回滾段, 爲回滾段設置較大的EXTENT以及較大的MINEXTENTS
B. 回滾段被破壞
因爲回滾段被破壞, 形成事務沒法將修改前的內容(read-consistent snapshot) 放入回滾段, 也會產生ORA-01555錯誤.
(即:事務被修改而且沒有提交,以後事務所在回滾段損壞,這時在查詢這個事務時就會報ora-01555錯誤)
解決方法: 將被破壞的回滾段OFFLINE, 刪除重建.
C. FETCH ACROSS COMMIT
當一個進程打開一個CURSOR, 而後循環執行FETCH, UPDATE, COMMIT, 若是更新的表與FETCH的是同一個表, 就極可能發生ORA-01555錯誤.
解決方法:
a. 使用大的回滾段
b. 減小提交頻率(可參見本論壇"如何避免一個PROCEDURE被重複調用"一貼中, 無名朋友的回帖)
以上兩種方法只能減小該錯誤發生的可能, 不能徹底避免. 若是要徹底避免, 須從執行方法着手, 能夠用如下兩種方法:
c. 創建一個臨時表, 存放要更新的表的查詢列(如主鍵及相關的條件列), 從臨時表FETCH, 更新原來的表.
d. 捕獲ORA-01555錯誤, 關閉並從新打開CURSOR, 繼續執行循環:
D. 延時塊清除
* Delayed logging block cleanout(延時塊清除)是ORACLE用來提升寫性能的一種機制: 當修改操做(INSERT/UPDATE/DELETE)發生時, ORACLE將原有的內容寫入回滾段, 更新每一個數據塊的頭部使其指向相應的回滾段, 當該操做被COMMIT時, ORACLE並再也不從新訪問一遍全部的數據塊來確認全部的修改, 而只是更新位於回滾段頭部的事務槽來指明該事務已被COMMIT, 這使得寫操做能夠很快結束從而提升了性能接下來的任何訪問該操做所修改的數據的操做會使先前的寫操做真正生效, 從而訪問到新的值. Delayed logging block cleanout 雖然提升了性能,但卻可能致使ORA-01555. 這種狀況下, 在OPEN/FETCH前對該表作全表掃描(保證全部的修改被確認)會有所幫助.
E 不適當的OPTIMAL參數:
過小的OPTIMAL參數會使回滾段很快被SHRINK, 形成後續讀取操做訪問時, 先前的內容已丟失,仔細設計OPTIMAL參數, 不要讓回滾段過於頻繁的EXTEND/SHRINK有助於問題的解決。
F DB BLOCK BUFFER過小
若是讀一致性所請求的塊的先前內容在緩衝區中, 那麼就不用去訪問回滾段,而若是緩衝區過小, 使得先前版本的內容在CACHE中的可能性變小, 從而必須頻繁的訪問回滾段來獲取先前的內容, 這將大大增大ORA-01555發生的可能。
oracle 塊延遲清除(delayed block cleanout) 理解
爲了保證事務的回退和知足多用戶的CR, oracle引入了undo 機制, 因爲undo是循環使用的,在一個事務完成過程當中,它與redo相互配合,其中undo在一次事務中須要完成如下工做:
(1) Transaction 開始前回滾段獲取一個ITL(事務槽),分配空間, 記錄事務信息
(2) Transaction 提交後,redo完成記錄,同時還清除回滾段的事務信息 包括行級鎖,ITL信息(commit 標誌,SCN等)
清除這些事務段的信息的過程就叫作塊清除, 在完成塊清除時, 咱們本事務修改的數據塊就會存在兩種可能
(1) 全部的數據塊還保存在 buffer cache 中
(2)部分數據塊或者是所有數據塊因爲LRU管理已經被刷出了buffer cache。
oracle爲了考慮到塊清除的成本,以及性能,會做如下兩種方式的塊清除處理:
(1)快速塊清除(fast block cleanout), 當事務修改的數據庫所有保存在buffer cache 而且修改數據塊的數據量沒有超過 cache buffer 的 10%,快速清除事務信息。
(2)延遲塊清除(delayed block cleanout) 當修改的數據塊的閥值超過10% 或者本次事務相關的數據塊已經被刷出了 buffer cache, oracle 會下次訪問此block 時再清除事務信息。