?
?
一、回滾段的作用:
??? 回滾段用于存放數據修改之前的值(也包括數據修改前的位置)。回滾段的頭部包含正在使用的該回滾段事務的信息。一個事務只能使用一個回滾段來存放它的回滾信息,而一個回滾段可以存放多個事務的回滾信息。
回滾段用于對數據庫修改時, 保存原有的數據, 以便稍后可以通過使用ROLLBACK來恢復到修改前的數據;另外, 回滾段可以為數據庫中的所有進程提供讀一致性. 因此, 回滾段設置的合理與否, 直接影響到數據庫的性能, 在更新密集的OLTP應用中,更是如此.
?
??? 其具體作用有以下幾項:
?
???
事務回滾:
???
當事務修改表中數據的時候,該數據修改前的值(即前影像)會存放在回滾段中,當用戶回滾事務(ROLLBACK)時,ORACLE將會利用回滾段中的數據前影像來將修改的數據恢復到原來的值。
???
事務恢復:
??? 當事務正在處理的時候,例程失敗,回滾段的信息保存在重做日志文件中,ORACLE將在下次打開數據庫時利用回滾來恢復未提交的數據。
???
讀一致性:
??? 當一個會話正在修改數據時,其他的會話將看不到該會話未提交的修改。而且,當一個語句正在執行時,該語句將看不到從該語句開始執行后的未提交的修改(語句級讀一致性)。當ORACLE執行SELECT語句時,ORACLE依照當前的系統改變號(SYSTEM CHANGE NUMBER-SCN)來保證任何前于當前SCN的未提交的改變不被該語句處理。可以想象:當一個長時間的查詢正在執行時,若其他會話改變了該查詢要查詢的某個數據塊,ORACLE將利用回滾段的數據前影像來構造一個讀一致性視圖。?
事務級的讀一致性:
ORACLE一般提供SQL語句級(SQL STATEMENT LEVEL)的讀一致性,可以用以下語句來實現事務級的讀一致性:
SET TRANSACTION READ ONLY;
或:
SET TANNSACTION SERIALIZABLE;
以上兩個語句都將在事務開始后提供讀一致性。需要注意的是,使用第二個語句對數據庫的并發性和性能將帶來影響。
?
?
?
二、回滾段的類型:
?
?
??? 1、系統回滾段:
??? 當數據庫創建后,將自動創建一個系統回滾段,它位于SYSTEM表空間,用于處理涉及系統的CataLog的事物(比如大多數的DDL)。
??? 注意:不要把System回滾段放在其他的表空間中,并且應該永遠保持ONLINE狀態。
?
??? 2、非系統回滾段:
??? 擁有多個表空間的數據庫至少應該有一個非系統回滾段,用于存放非系統表空間中對象的數據前影像。
??? 非系統回滾段又分為私有回滾段和公有回滾段,私有回滾段應在參數文件的ROLLBACK_SEGMENTS參數中列出,以便例程啟動時自動使其ONLINE(也可通過使用Alter Rollback Segment XXX Online來使用某一個回滾段)。公有回滾段一般在OPS(ORACLE并行服務器)中出現,將在例程啟動時自動ONLINE。
??? 建議將每個實例的Private回滾段放置到訪問比較快的本地設備上。
?
??? 3、DEFERED回滾段:
??? 該回滾段在表空間離線(OFFLINE)時由系統自動創建,當表空間再次在線(ONLINE)時由系統自動刪除,用于存放表空間離線時產生的回滾信息。
?
?
?
三、回滾段的使用:
?
?
(1) 創建回滾段?
create
rollback
segment
rb01
tablespace
rbs1
storage
(
????????
initial
100
K
????????
next
100
K
????????
minextents
20
????????
maxextents
100
????????
optimal
2000
K );
注意:
回滾段可以在創建時指明PRIVATE或PUBLIC,一旦創建將不能修改。
MINEXTENTS 必須大于等于2
PCTINCREASE必須是0
OPTIMAL如果要指定,必須大于等于回滾段的初始大小(由MINEXTENTS指定)
?
建議:
一般情況下,INITIAL=NEXT
設置OPTIMAL參數來節約空間的使用
不要設置MAXEXTENTS為UNLIMITED
回滾段應創建在一個特定的回滾段表空間內
?
(2) 更改ONLINE/OFFLINE狀態
alter
rollback
segment
rb01
online
;
alter
rollback
segment
rb01
offline
;
當回滾段創建后,回滾段是離線的,不能被數據庫使用,為了使回滾段被事務利用,必須將回滾段在線。
如果有事務正在使用該回滾段,運行offline命令后,回滾段的狀態將是PENDING OFFLINE。事務結束后,狀態將改為OFFLINE,可以通過V$ROLLSTAT查詢回滾段的狀態。
(3) 更改OPTIMAL參數
alter
rollback
segment
rb01
storage
(
maxextents
200
????????
optimal
2048
K );
(4) 縮小回滾段
alter
rollback
segment
rb01
shrink
to
2048
K;
--
有
OPTIMAL
參數時
,
縮小到
OPTIMAL
值
alter
rollback
segment
rb01
shrink
;
--
沒有
OPTIMAL
參數時
,
縮小到
MINEXTENTS
所對應的值
(5) 修改INITIAL/NEXT參數
--
修改
NEXT
時
,
總應該同時修改
INITIAL.
--INITIAL
參數無法直接修改
,
只能先
DROP,
然后再
CREATE.
drop
rollback
segment
rb01;
create
rollback
segment
rb01
tablespace
rbs1
storage
(
initial
100
K
????????
next
100
K
????????
minextents
20
????????
maxextents
121
????????
optimal
2000
K );
(6) 在事務中使用特定的回滾段
set
transaction
use
rollback
segment
rb01;
?
注意:
1、某個事務只能放在一個回滾段中,事務不可能分回滾段存放;一個回滾段可以存儲多個事務。
2、幾個事務可以寫在回滾段的同一個區,一個事務也可以寫在回滾段的不同區。
3、回滾段的block只能包含一個事務的信息。
4、當回滾段區的所有塊用完而事務還需要更多的回滾空間時,回滾段的指針將移到下一個區。當最后一個區用完,指針將移到第一個區的前面。回滾段指針移到下一個區的前提是下一個區沒有活動的事務,同時指針不能跨區。當下一個區正在使用時,事務將為回滾段分配一個新的區,這種分配稱為回滾段的擴展(extend)。回滾段將一直擴展到該回滾段區的個數到達回滾段的參數MAXEXTENTS的值時為止。
?
??? 例如:兩個事務使用同一個回滾段,該回滾段有四個區:
??? 1.事務在進行中,它們正在使用回滾段的第三個區;
??? 2.當兩個事務產生更多的回滾信息,它們將繼續使用第三個區;
??? 3.當第三個區滿后,事務將寫到第四個區,當事務開始寫到一個新的區時,稱為翻轉(WRAP);
??? 4.當第四個區用滿時,如果第一個區是空閑或非活動(使用該區的所有事務完成而沒有活動的事務)的,事務將接著使用第一個區。
(7) 常用的有關回滾段的系統數據字典
DBA_ROLLBACK_SEGS?
--DBA_SEGMENTS
中的
ROLLBACK
類型
V$ROLLNAME
V$ROLLSTAT
V$TRANSACTION?????
--V$SESSION
回滾段的基本信息,
例:
SQL>SELECT segment_name,tablespace_name,owner,status FROM dba_rollback_segs;
?
回滾段的統計信息,
例:
SQL>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;
?
回滾段的當前活動事務,例:
SQL>SELECT s.username,t.xidusn,t.ubafil,t.ubablk,t.used_ublk
FROM v$session s,v$transaction t
WHERE s.saddr=t.ses_addr;
USERNAME XIDUSN UBAFIL UBABLK USED_UBLK
????------- -------- ----------- ----------- -----------
SYSTEM 2 2 7 1
SCOTT 1 2 163 1
2 rows selected.
?
?
?
?
三、回滾段的參數設置:
?
??? 精確的回滾段的數量及大小的計算涉及很多方面:
??? 1、應用的類型(OLTP/OLAP/BATCH)
??? 2、同時進行的事物的數量
??? 3、DML語句的類型
??? 4、每個事物處理的數據量
??? 5、……
??? 回滾段使用的建議:
???
1、OLTP系統應使用小但較多的回滾段,每四個事務一個回滾段;每個回滾段不要超過十個事務。
??? 2、OLAP系統/批處理系統應使用少量的大回滾段;每個事務一個回滾段。
??? 3、OLTP/OLAP混合型系統中, 應專門設置一個或幾個大的回滾段, 平時設置為OFFLINE, 使用時通過使用SET TRANSACTION USE ROLLBACK SEGMENT XXX來使用它。
?????? 這些回滾段應使用OPTIMAL參數,以便在不使用時,可以SHRINK到一個較小的尺寸;
??? 3、在很難計算準確的數量、大小時,可用"偏大不偏小"的原則;
??? 4、所有的回滾段的INITIAL/NEXT參數應設為相同, 只有建議3中提到的大回滾段例外;
??? 5、不要將回滾段的MAXEXTENTS設為UNLIMITED, 回滾段所在表空間也不要設為AUTOEXTEND方式, 否則將會使得由于某個不正常的事務導致整個數據庫處于失控狀態。
?
?
?
?
四、回滾段的常見錯誤及解決方法:
?
?
(1) 回滾段空間不夠?
???
??? ORA-01562 - failed to extend rollback segment number string
??? 回滾段空間不夠的原因一般有以下幾種情況:?
??? A. 回滾段所在表空間剩余的空閑空間太小, 無法分配下一個EXTENT.?
??? B. 回滾段擴展次數已經達到MAXEXTENTS限制
?
??? 解決方法:?
??? A. 擴大回滾段所在表空間?
??? B. 設置較大的MAXEXTENTS參數?
??? C. 為回滾段設置OPTIMAL參數?
??? D. 用較大的EXTENT參數重新創建回滾段?
??? E. 將導致ORA-1562錯誤的DML語句改為分段執行:
(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. 回滾段太少/太小?
??????? 數據庫中有太多的事務修改數據并提交, 就會發生已提交事務曾使用的空間被重用, 從而造成一個延續時間長的查詢所請求的數據已經不在回滾段中.?
??? 解決方法: 創建更多的回滾段, 為回滾段設置較大的EXTENT以及較大的MINEXTENTS
?
??? B. 回滾段被破壞?
??????? 由于回滾段被破壞, 造成事務無法將修改前的內容(read-consistent snapshot) 放入回滾段, 也會產生ORA-01555錯誤.?
??? 解決方法: 將被破壞的回滾段OFFLINE, 刪除重建.
?
??? C. FETCH ACROSS COMMIT?
??????? 當一個進程打開一個CURSOR, 然后循環執行FETCH, UPDATE, COMMIT, 如果更新的表與FETCH的是同一個表, 就很可能發生ORA-01555錯誤.
???
解決方法:?
??? a. 使用大的回滾段?
??? b. 減少提交頻率
????? 以上兩種方法只能減少該錯誤發生的可能, 不能完全避免. 如果要完全避免, 須從執行方法著手, 可以用以下兩種方法:?
??? c. 建立一個臨時表, 存放要更新的表的查詢列(如主鍵及相關的條件列), 從臨時表FETCH, 更新原來的表.?
??? d. 捕獲ORA-01555錯誤, 關閉并重新打開CURSOR, 繼續執行循環:?
示例(示例程序的思路來源自ORACLE的UTLIP.SQL, 有興趣的朋友可直接閱讀該程序, 位置在RDBMS\ADMIN下, 程序很短, 容易讀):
DECLARE
? LAST_PK NUMBER := 0;
? V_THEROWID ROWID;
? CURSOR C1 IS
??? SELECT ROWID, PK, ... FROM SMPLE
??? WHERE PK > LAST_PK
??? AND othercondition
??? ORDER BY PK;
BEGIN
? OPEN c_SOURCE;
? LOOP
??? BEGIN
????? FETCH C1 INTO v_THEROWID, v_PK;
????? EXIT WHEN C1%NOTFOUND;
????? EXCEPTION WHEN OTHERS THEN
????? IF SQLCODE = -1555 THEN -- snapshot too old, re-execute fetch query
??????? CLOSE C1;
??????? OPEN c_SOURCE;
??????? GOTO NEXTLOOP01555;
????? ELSE
??????? RAISE;
????? END IF;
??? END;
? LAST_PK := PK;
? PROCESS,UPDATE AND COMMIT<>NULL;
? END LOOP;
? CLOSE C1;
END;
?
??? D. 其它原因:
???
* Delayed logging block cleanout是ORACLE用來提高寫性能的一種機制: 當修改操作(INSERT/UPDATE/DELETE)發生時, ORACLE將原有的內容寫入回滾段, 更新每個數據塊的頭部使其指向相應的回滾段, 當該操作被COMMIT時, ORACLE并不再重新訪問一遍所有的數據塊來確認所有的修改, 而只是更新位于回滾段頭部的事務槽來指明該事務已被COMMIT, 這使得寫操作可以很快結束從而提高了性能接下來的任何訪問該操作所修改的數據的操作會使先前的寫操作真正生效, 從而訪問到新的值. Delayed logging block cleanout 雖然提高了性能, 但卻可能導致ORA-01555. 這種情況下, 在OPEN/FETCH前對該表做全表掃描(保證所有的修改被確認)會有所幫助.
???
* 不適當的OPTIMAL參數: 太小的OPTIMAL參數會使回滾段很快被SHRINK, 造成后續讀取操作訪問時, 先前的內容已丟失. 仔細設計OPTIMAL參數, 不要讓回滾段過于頻繁的EXTEND/SHRINK有助于問題的解決.
???
* DB BLOCK BUFFER太小: 如果讀一致性所請求的塊的先前內容在緩沖區中, 那么就不用去訪問回滾段. 而如果緩沖區太小, 使得先前版本的內容在CACHE中的可能性變小, 從而必須頻繁的訪問回滾段來獲取先前的內容, 這將大大增大ORA-01555發生的可能.
?
-The End-