ORACLE 回滚段详解
ORACLE 回滾段
?
回滾段概述?
回滾段用于存放數據修改之前的值(包括數據修改之前的位置和值)。回滾段的頭部包含正在使用的該回滾段事務的信息。一個事務只能使用一個回滾段來存放它的回滾信息,而一個回滾段可以存放多個事務的回滾信息。?
回滾段的作用?
事務回滾:當事務修改表中數據的時候,該數據修改前的值(即前影像)會存放在回滾段中,當用戶回滾事務(ROLLBACK)時,ORACLE將會利用回滾段中的數據前影像來將修改的數據恢復到原來的值。?
事務恢復:當事務正在處理的時候,例程失敗,回滾段的信息保存在重做日志文件中,ORACLE將在下次打開數據庫時利用回滾來恢復未提交的數據。?
讀一致性:當一個會話正在修改數據時,其他的會話將看不到該會話未提交的修改。而且,當一個語句正在執行時,該語句將看不到從該語句開始執行后的未提交的修改(語句級讀一致性)。當ORACLE執行SELECT語句時,ORACLE依照當前的系統改變號(SYSTEM CHANGE NUMBER-SCN)來保證任何前于當前SCN的未提交的改變不被該語句處理。可以想象:當一個長時間的查詢正在執行時,若其他會話改變了該查詢要查詢的某個數據塊,ORACLE將利用回滾段的數據前影像來構造一個讀一致性視圖。?
?
回滾段的類型
?
回滾段可分為系統回滾段和非系統回滾段, 其中非系統回滾段又分為PUBLIC回滾段和PRIVATE回滾段。
?
回滾段:1 系統回滾段
??????? 2 非系統回滾段:(1)PUBLIC回滾段
??????????????????????? (2)PRIVATE回滾段
?
系統回滾段用于處理涉及系統的CATALOG的事物(比如大多數的DDL), 它位于SYSTEM表空間, 由于只有SYSTEM表空間可以隨時保持可用, 因此,不要把SYSTEM回滾段放在其他的表空間中.
?
原則1: 系統回滾段應放在SYSTEM表空間中, 并且應該永遠保持ONLINE狀態.
?
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),當當前區用滿后移到下一個區。幾個事務可以寫在回滾段的同一個區,但每個回滾段的塊只能包含一個事務的信息。
例如(兩個事務使用同一個回滾段,該回滾段有四個區):
1、事務在進行中,它們正在使用回滾段的第三個區;
2、當兩個事務產生更多的回滾信息,它們將繼續使用第三個區;
3、當第三個區滿后,事務將寫到第四個區,當事務開始寫到一個新的區時,稱為翻轉(WRAP);
4、當第四個區用滿時,如果第一個區是空閑或非活動(使用該區的所有事務完成而沒有活動的事務)的,事務將接著使用第一個區。
?
回滾段的查詢
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錯誤。
?
1、 回滾信息量
?????? 存儲于回滾段中的回滾信息量取決于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 時再清除事務信息。
?
?
參考:
http://www.yesky.com/143/208643.shtml
http://www.dbtan.com/2010/01/ora-01555-reason-and-solution.html
http://blog.163.com/xb_guo/blog/static/2008392472011112613232758/
http://blog.csdn.net/47522341/article/details/3862678
http://www.examw.com/oracle/zhonghe/119456/
http://blog.itpub.net/8117479/viewspace-705530/
?
?
總結
以上是生活随笔為你收集整理的ORACLE 回滚段详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ERROR 2002 (HY000):
- 下一篇: 关于嵌套循环