淺談Oracle的undo管理

tangyunoracle發表於2013-12-27
1、什麼是undo
    當我們對資料執行修改操作時,資料庫會生成undo 資訊,這樣一旦執行的事務或語句由於某種原因失敗,或者發出一條ROLLBACK 語句請求回滾,就可以利用這些undo資訊將資料放回到修改前的樣子。undo 資訊儲存在一組特殊的段中,這稱為undo 段(undo segment)。
select segment_name,tablespace_name,status,block_id,file_id from dba_rollback_segs;
2、undo有什麼作用
在Oracle資料庫中,undo主要有三大作用:提供一致性讀(Consistent Read)、回滾事務(Rollback Transaction)以及例項恢復(Instance Recovery)。
2.1、一致性讀(Consistent Read)
    一致性讀是相對於髒讀(Dirty Read)而言的。假設某個表T中有10000條記錄,獲取所有記錄需要15分鐘時間。當前時間為9點整,某使用者A發出一條查詢語句:select * from T,該語句在9點15分時執行完畢。當使用者A執行該SQL語句到9點10分的時候,另外一個使用者B發出了一條delete命令,將T表中的最後一條記錄刪除並提交了。那麼到9點15分時,A使用者將返回多少條記錄?正確的應該是10000條記錄。很明顯,在 9點鐘那個時間點發出查詢語句時,表T中確實有10000條記錄,只不過由於I/O的相對較慢,所以才會花15分鐘來完成所有記錄的檢索。
這是因為ORACLE透過構造CR(consistent read)塊提供一致讀的方式,保證了資料的完整性。具體的實現方式如下:
使用者在進行查詢時oracle會先記錄當時的SCN號,當查詢讀到被B使用者更新刪除記錄後的塊時,發現這個塊頭部ITL槽中的SCN號比查詢開始時的SCN號大,這樣就會在回滾段中尋找這個塊的前映像資料,找到這個資料的前映像後,把前映像和CURRENT的資料塊進行合併,就形成了一個CR BLOCK,透過查詢CR BLOCK就可以得到一致性的資料。
2.2、回滾事務(Rollback Transaction)
當使用者發出一個update 操作後,會在回滾段中記錄更新記錄的前映像資料,如果使用者再發出rollback命令撤銷資料變化時,Oracle利用記錄在ITL槽裡記錄的undo 塊的地址找到該undo塊,然後從中取出變化前的值,並放入資料塊中,從而對事務所作的變化進行回滾。
2.3、例項恢復(Instance Recovery)
例項恢復則是在SMON程式完成前滾並開啟資料庫以後發生。SMON程式會去檢視undo segment頭部(所謂頭部就是undo segment裡的第一個資料塊)記錄的事務表(每個事務在使用undo塊時,首先要在該undo塊所在的undo segment的頭部記錄一個條目,該條目裡記錄了該事務相關的資訊,其中包括是否提交等),將其中既沒有提交也沒有回滾,而是在例項崩潰時被異常終止的事務全部回滾。
3、回滾段管理方式
oracle的undo管理有兩種方式,自動管理和手動管理,可以使用 undo_management 引數來進行控制。當設定為auto時使用undo表空間的方式來自動管理undo段,如果設定為manual則使用rollback segment方式儲存undo資訊。
    oracle9i 以後開始使用undo自動管理,手動管理方式只在特殊的場合下才會偶爾使用到。後面在介紹undo恢復時再做相應介紹。
說到自動管理,首先要介紹UNDO_RETENTION引數,這個引數用來指定undo 記錄儲存的最長時間,預設為900秒,可以動態的進行修改。這個引數不是指undo中的資料在undo表空間中一定要儲存900秒,例如當一個新事務開始的時候,如果發現undo表空間已經被寫滿,則新事務的資料會自動覆蓋已提交事務的資料,而不管這些資料是否已存放夠900秒。同時也不是指undo_retention 中指定的時間一過,已經提交事務中的資料就立刻無法訪問,通常它只是失效,只要沒有被別的事務覆蓋,它就會仍然存在,這時我們可以使用flashback 特性檢視錶在更新前不同時刻的資料。
因此UNDO表空間中的資料在不同時段就會有不同的狀態顯示,在dba_undo_extents 資料字典裡記錄了UNDO中每個區段的狀態.
SQL> SELECT   tablespace_name, status, SUM (bytes) / 1024 / 1024 "Bytes(M)"
    FROM   dba_undo_extents
    GROUP BY   tablespace_name, status;
TABLESPACE_NAME                STATUS      Bytes(M)
---------------- --------- ----------
UNDOTBS2                       EXPIRED       1.4375
UNDOTBS2                       UNEXPIRED       .375
UNDOTBS2                       ACTIVE          .125
UNDOTBS1                       EXPIRED           22

其中:
ACTIVE :未提交的回滾資料,該資料所關聯的事務並未提交,用於實現讀一致性,所以該資料不能被其它事務的資料所覆蓋 。
UNEXPIRED:已經提交但未過期的回滾資料,該資料關聯的事務已經提交,但是仍受到undo retention引數保持時間的影響,當undo表空間中沒有可用的資料塊時,這些資料塊會直接被覆蓋而進行重用。
EXPIRED: 事務已經提交,而且資料儲存時間已經超過undo retention引數指定的時間,屬於已經過期的資料.可以被隨時重用。
需要說明的是,當設定表空間啟動Guarantee特性時,UNEXPIRED型別的塊就必須要等到undo_retention 指定時間過期後才能被重用。
4、undo段的常見問題及維護操作
4.1、Oracle ORA-01555 快照太舊
ORA-01555是oracle中常見的一個錯誤,例如當我們進行的事務需要使用undo資料來構造CR塊的時候,如果對應的undo資訊已經被覆蓋時,就會報出ora-01555錯誤。
對於這種情況,通常有以下幾種解決辦法。
1、最佳化出錯的SQL,減少語句的查詢時間。
2、增加UNDO表空間大小
3、增加undo_retention 時間,預設只有15分鐘
4、避免頻繁的提交
4.2、Oracle ORA-1628 回滾段達到32765最大值
  undo表空間自動管理方式下,單個回滾段的最大區數為32765,我們知道一個事務只能使用一個回滾段,當一個大事務在進行大量資料更新時,所使用的回滾段不能完全存放這個事務的前映像資料時, 就可能會出現這種情況,這種情況下只能透過切換undo表空間來排除故障。避免這種故障的根本原因還是要最佳化相應的SQL語句,減少UNDO塊的產生。
出現ORA-1628故障時至少會有一個回滾段的狀態會顯示為FULL,如下表資訊:
SQL> select segment_name,max_extents,status from dba_rollback_segs;
SEGMENT_NAME                   MAX_EXTENTS STATUS
----------------------- ----------- --------
SYSTEM                               32765 ONLINE
_SYSSMU1$                            32765 OFFLINE
_SYSSMU2$                            32765 OFFLINE
_SYSSMU3$                            32765 FULL
_SYSSMU4$                            32765 OFFLINE
_SYSSMU5$                            32765 OFFLINE
_SYSSMU6$                            32765 OFFLINE

4.3、UNDO表空間損壞後的資料恢復
如果資料庫在執行過程中出現undo表空間故障時,通常可以透過線上新建undo表空間,並且切換為預設表空間後就能快速解決故障。假如undo損壞而且資料庫在關閉狀態,如果沒有任何有效的備份時,可以透過修改undo手動管理的方式來啟動資料庫。
這裡用一個案例來說明恢復的過程。
系統環境:  oracle 10.2.0.4 非歸檔方式,無有效備份
故障現象:
   資料庫無法啟動,alert日誌中有大量的ora-600 錯誤
ORA-00600: internal error code, arguments: [2662], [1], [3008810928], [1], [3008849117], [8388617], [], []
ORA-00600: internal error code, arguments: [4194], [15], [6], [], [], [], [], []
Mon May 23 18:36:46 2011
Doing block recovery for file 2 block 336654
Block recovery from logseq 2200, block 63 to scn 7317545555
故障分析:
根據提示資訊,可以查到是undo表空間的資料檔案出現壞塊造成資料庫無法啟動,因資料庫為非歸檔方式,沒有有效的undo備份檔案,這種情況下就可以使用undo手動管理的方式啟動資料庫,詳細可以參考Metalink文章[ID 281429.1] 。
下面是大概的步驟介紹。
1、啟動到nomount 狀態,備份引數檔案
2、修改引數檔案,undo_management=manual
3、使用新的引數檔案啟動資料庫
4、建立新的回滾段
SQL> create rollback segment r01;
5、設定回滾段為online
SQL> alter rollback segment r01 online;
6、建立表空間undotbs2
7、停庫,修改引數為表空間自動管理,
8、重啟啟動資料庫。
---------------------End-----------------------------------------------------------

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/24930246/viewspace-1064924/,如需轉載,請註明出處,否則將追究法律責任。

相關文章