復原段可以說是用來保持資料變化前映象而提供一致讀和保障事務完整性的一段磁碟儲存地區。當一個事務開始的時候,會首先把變化前的資料和變化後的資料先寫入日誌緩衝區,然後把變化前的資料寫入復原段,最後才在資料緩衝區中修改(日誌緩衝區內容在滿足一定的條件後可能被寫入磁碟,但在事務提交的時候日誌必須寫入磁碟,而資料緩衝區中的資料依賴於檢查點的發生和DBWR進程的活動)
Rollback是一個代價昂貴的操作,如果一個系統的交易回復率過高,應該檢查系統是否正常或者程式設計思路是否存在問題。查詢資料庫啟動依賴的
交易回復率,如果發現太高,一定要引起重視。
--查詢回退率的sql
SELECT NAME, VALUE
FROM v$sysstat
WHERE NAME IN ('user commits', 'transaction rollbacks');
關於復原段的資料,如果是delete操作,則復原段將回記錄整個行的資料;如果是update,則只記錄被修改了的欄位的變化前的資料(前映像);如果是insert,則只記錄插入記錄的rowid。所以,假如commit,那麼復原段中簡單標記該事務已經提交;假如rollback,則操作是 delete的話,把復原段中的資料重新寫回資料區塊,操作是update的話則把變化前的資料修改回去,操作是insert的話則根據rowid把該記錄刪除。這個過程是保障事務的完整性,保障資料不會丟失。
一致性讀(consisitent reads) Oralce的查詢集是根據時間點來判定的。Oracle內部通過系統改變號SC作為相對時間點的標準,任何對資料庫的改變都會產生SCN,對資料區塊的資料改變的時候會把該改變所對應的SCN記錄在塊中。假設查詢開始的時候SCN為T,則在查詢所掃描的資料區塊中,如果資料區塊的COMMIT SCN小魚T,則查詢接受該資料,如果COMMIT SCN大於T或者說還沒有產生COMMIT SCN,則查詢會嘗試去復原段中尋找資料。這保證了資料的讀取時間點的一致性。
在通過復原段中擷取資料的時候,本質上是把資料緩衝區中的資料區塊做一個拷貝,然後將復原段中記錄的內容恢複到該塊中,然後查詢使用這個塊來進行讀取。
系統復原段和延遲復原段
SYSTEM復原段是建立在系統資料表空間中,主要用於系統級的事務和分配普通事務於其他復原段上。當手工建立資料後需要建立普通復原段之前必須首先建立系統復原段。按oracle文檔說,當普通事務異常多的事情可能會使用系統復原段的情況。正常情況下,系統復原段主要用於兩個方面:一是系統事務,不如針對資料字典的操作的truncate table 和 drop table。如果truncate or drop table的過程中沒有成果,則系統會根據系統復原段中的資料字典操作資訊對該DDL操作進行回退。另一個方面,就是延遲復原段(Deferred Rollback Segment)。延遲復原段表示,當我們使一個資料表空間OFFLINE之後,由於資料表空間不可用,這個時候若有交易資料位於該空間並執行復原命令,在client看起來該事務已經復原,但對於資料區塊來說復原並沒有真正完成,這個時候資料庫將該復原資訊寫入系統復原段(這就是延遲復原段),等資料表空間重新ONLINE的時候,資料區塊從系統復原段中將復原資訊寫入資料表空間。
回退段的設定和管理
Oracle9i之前需要手動設定回退段,我們需要考慮如下問題:
1.系統並發事務數有多少
2.系統是否存在大查詢或者大事務,是否頻繁
3.能提供給系統復原段的資料表空間的磁碟空間是多少
9i的UNDO TABLESPACE
從9i開始,推薦使用UNDO TABLESPACE,系統自動管理復原段
Sql> show parameter undo
undo_management string AUTO
undo_retention integer 900
undo_tablespace string UNDOTBS1
UNDO TABLESPACE變的很大,我們不能縮小,這個時候我們需要考慮建立新的UNDO TABLESPACE,然後換到新的資料表空間。這時即使UNDO資料表空間有事務也可以切換,只不過不能立即刪除該資料表空間,切換之後等到原來的資料表空間中所有的事務出力完畢,並且達到undo_retention的時間後,就可以drop原來的UNDO資料表空間。
SQL> alter system set undo_tablespace = undotbs02;
System altered.
切換了UNDO資料表空間後應該修改pfile或者spfile,使得下次啟動應用新的UNDO資料表空間。
復原段著名的ORA-01555問題
從應用角度來看ORA-01555
1.查詢執行時間太長。首先是最佳化查詢,然後考慮在資料區塊不繁忙的時候運行,最後考慮加大復原段。
2.過渡頻繁的提交。把能夠成批提交的單條事務改成成批提交
3.exp的時候使用而來consistent = y. 這個參數主要是為了保證在exp的時候使得所有的到處的表在時間點上具有一致性,避免存在主外鍵關係的表由於不同的時間點的不一致而破壞了資料的完整性。建議該操作在系統閒置時候進行。
4.由於復原段回縮導致復原段還沒有迴圈使用的情況下就出現了復原段中找不著資料的情況。只能加大復原段增大optimal設定。
UNDO scripts
查詢資料區塊當前某個session的事務所使用的復原段大小
SELECT b.SID, a.xidusn, a.xidusn
FROM v$transaction a, v$session b
WHERE a.addr = b.taddr
復原段資料表空間中的一個資料檔案丟失或者損害的恢複方法
…………….
由於對應的undo block/或者undo header slot資訊被覆蓋,導致consistent read不能完成, 系統會報出ora-01555的錯誤資訊..
出現這種情況的原因可能有以下幾種.
1. 對於早期的manual undo, 可能是由於系統設定了optimal size, rollback segment wrap 導致部分undo資訊被丟棄..
2. 由於undo retention 設定的時間小於sql執行的長度,這樣從這條sql開始時候其他session產生的部分undo由於retention的原因被覆蓋,導致無法完成consistent read.
3. 由於commit over fetch loop. 導致transaction slot 被覆蓋,無法完成consistent read ..
ORA-01555錯誤淺析-- http://www.hellodba.com/Doc/ORA-01555_analysis(1).htm
總結出以下方法來解決1555錯誤問題:
1、擴大復原段
因為復原段是迴圈使用的,如果復原段足夠大,那麼那些被提交的資料資訊就能儲存足夠長的時間是那些大事務完成一致性讀取。
2、增加undo_retention時間
在undo_retention規定的時間內,任何其他事務都不能覆蓋這些資料。
3、最佳化相關查詢語句,減少一致性讀。
減少查詢語句的一致性讀,就降低讀取不到復原段資料的風險。這一點非常重要!
4、減少不必要的事務提交
提交的事務越少,產生的復原段資訊就越少。
5、對大事務指定復原段
通過以下語句可以指定事務的復原段:
SET TRANSACTION USE ROLLBACK SEGMENT rollback_segment;
給大事務指定復原段,即降低大交易回復資訊覆蓋其他事務的復原資訊的幾率,又降低了他自身的復原資訊被覆蓋的幾率。大事務的存在,往往是1555錯誤產生的誘因。
6、使用遊標時盡量使用顯式遊標,並且只在需要的時候開啟遊標,同時將所有可以在遊標外做的操作從遊標迴圈中拿出。
當遊標開啟時,查詢就開始了,直到遊標關閉。減少遊標的開啟時間,就減少了1555錯誤發生的幾率。