undo


1、重要概念

並行 DML 和 DDL 操作實際上可導致事務處理使用多個還原段。

還原段由 SYS 自動創建並始終歸其所有。由於還原段充當循環緩沖區,因此每個段最少包含兩個區。

還原表空間只在實例處於 MOUNT 狀態時才可恢復

除非啟用了保留時間保證,否則系統會忽略 UNDO_RETENTION。

UNDO_RETENTION 參數指定已提交的 Undo 信息要保留多長時間(單位為秒),默認為 900 秒(即 15 分鍾)。但是該值不是絕對的,也就是說,如果有其它事務需要 Undo 空間,而 Undo 空
間出現不足時,這些信息仍然會被覆蓋。為 只有當表空間設置為 GUARANTEE 時,才能確保已提交留 的數據保留 UNDO_RETENTION 參數設置的時間。RETENTION GUARANTEE 是表空間屬性而不是初
始化參數,此屬性只可使用 SQL 命令行語句來更改。
---通過更改 Undo 表空間來保證保留時間的語法是:
SQL>ALTER TABLESPACE undotbs1 RETENTION GUARANTEE;
---要將有保留時間保證的還原表空間返回到其常規設置,請使用以下命令:
SQL>ALTER TABLESPACE undotbs1 RETENTION NOGUARANTEE;
---查詢保留時間狀態:
SQL> SELECT RETENTION FROM DBA_TABLESPACES WHERE TABLESPACE_NAME LIKE 'UNDO%';

 
         

如果設置 UNDO_RETENTION 為 0,那么 Oracle 啟用自動調整 UNDO_RETENTION(auto tuning of undo_retention)以滿足最長運行查詢的需要,在告警日志文件中可以看到如下信息:
Autotune of undo retention is turned on.
可以通過設置“"_undo_autotune"=FALSE”來顯式的關閉自動調整 UNDO_RETENTION 功能。

Undo 主要有以下幾個作用:
(1) 事務回滾( (Rollback Transaction)

(2) 事務恢復( (Transaction Recovery)

(3) 提供一致性讀(Consistent Read)

---Undo 數據是如何實現一致性讀的呢?
在 Oracle 數據庫中的 Buffer Cache 中的數據塊上都會有最后一次修改數據塊時的 SCN。如果一個事務需要修改數據塊中數據,那么會先在回滾段中保存一份修改前數據和 SCN 的數據塊,然后再更新
Buffer Cache 中的數據塊的數據及其 SCN,並標識其為“臟”數據。當其它進程讀取數據塊時,會先比較數據塊上的 SCN 和自己發出 SQL 語句時刻的 SCN,分為以下兩種情況:
1 如果該數據塊頭部的 ITL 槽上記錄的 SCN 大於自己查詢時刻的 SCN,那么表示該塊被更新過,此時就要借助 Undo 塊了。在該數據塊頭部的 ITL 槽上記錄了對應的 Undo 塊的地址(Uba),
根據 Uba 就可以找到對應的 Undo 塊。如果發現該 Undo 塊的 ITL 槽的 SCN 號也較大,證明該 Undo 塊也不可用,那么需要在該塊的 ITL 槽上繼續尋找上一個 Undo 塊地址,層層遞歸,
最終找到 SCN 號比發出查詢的 SCN 號小的Undo 塊,將該 Undo 塊中的被修改前的數據取出,從而構建出發出 SQL 語句時刻的數據塊內容,這樣的數據塊叫做 CR(Consistent
Read)塊。
但是在查找的過程中,可能會發現當前 Undo 塊里記錄的 ITL 槽的 SCN號比上一個 Undo 塊里記錄的 SCN 號還要大。這種情況說明由於事務被提交或回滾,導致當前找到的 Undo塊里的數據已經被其它
事務覆蓋了,於是就無法再找出小於等於發出查詢時的那個時間點的 SCN 號,這時Oracle 就會拋出一個非常經典的錯誤
--ORA-1555,也就是 snapshot too old(快照過舊)的錯誤。
對於DELETE 來說,其 Undo 信息就是 INSERT,也就是說該構建出來的 CR 塊中就插入了被刪除的那條記錄。
2 如果數據塊頭部的 ITL 槽(事務槽)上記錄的 SCN 小於等於自己查詢時刻的 SCN,那么分為兩種情況:第一,若被查詢的塊上沒有活動的事務,則表示該塊沒有被更新過,是可用的,可以直接讀取該數 據塊上的數據;第二,若被查詢的塊上有活動的事務,則需要找 Undo 的前鏡像數據。
---Undo 段存儲的內容 Redo 中只會記錄少量信息,這些信息足以重演事務;同樣 Undo 中也只記錄精簡信息,這些信息足以撤銷事務。具體來說:
   對於 INSERT 操作,回滾段只需要記錄插入記錄的 ROWID,如果回退,那么只需將該記錄根據ROWID 刪除即可;
   對於 UPDATE 操作,回滾段只需要記錄被更新字段的舊值即可(前鏡像),回退時通過舊值覆蓋新值即可完成回滾;
   對於 DELETE 操作,Oracle 則必須記錄整行的數據,在回滾時,Oracle 通過一個反向操作恢復刪除的數據。
總結一下:常 對於相同數據量的數據操作,通常 INSERT 產生最少的 Undo ,UPDATE 產生的 Undo 居中,而 而 DELETE 操作產生的 Undo 最多。所以,當一個大的 DELETE 操作失敗或者回滾,
總是需要很長的時間,並且會有大量的 Redo 生成。所以通常在進行大規模數據刪除操作時,推薦通過分批刪除分次提交,以減少對於回滾段的占用和沖擊
塊清除(Block Cleanout)是指清除存儲在數據塊頭部與鎖相關的信息,其實質是在清除塊上的事務信息,包括數據的行級鎖和 ITL 信息(包括提交標志、SCN 等),塊清除不需要生成 Redo 日志。
Oracle 的塊清除有兩種: 快速塊清除(Fast
Commit Cleanout) )和 延時塊清除(Delayed Block Cleanout) )。 建議在批量加載了數據后,通過運行 DBMS_STATS 實用程序來收集統計信息,就能自然的完成塊清除工作。Oracle 提供了一個內部事件(10203 事件)可以用來跟蹤數據庫的塊清除操作,可以通過以 下命令設置: ALTER SYSTEM SET EVENTS '10203 trace name context forever';
Oracle Undo 段中區有 3 種狀態(DBA_UNDO_EXTENTS 的 STATUS 列):ACTIVE、EXPIRED 和UNEXPIRED:
 ACTIVE 即未提交的 Undo 信息(活動):表示事物還在活動,該值對應的 Undo 段的DBA_ROLLBACK_SEGS.STATUS 一定是 ONLINE 狀態,一旦沒有活動的事務在使用 Undo 段,那么對
應的 Undo 段就變成 OFFLINE 狀態。ACTIVE 狀態的 Undo 區不會被覆蓋。
 EXPIRED 即過期的 Undo 信息(過期):表示事務已經提交且超過了 UNDO_RETENTION 指定時間,該狀態可以被覆蓋使用。
 UNEXPIRED 即提交的 Undo 信息(未過期):表示事務已經提交但是還沒有超過UNDO_RETENTION 指定時間,該狀態可以被覆蓋使用。
自動Automatic Undo Retention Tuning 這個特性。設置的 undo_retention 參數只是一個指導值,,Oracle 會自動調整 Undo (會跨過 undo_retention 設定的時間) 來保證不會出現 Ora-1555 錯誤.
通過查詢V$UNDOSTAT(該視圖記錄4天以內的UNDO表空間使用情況,超過4天可以查詢DBA_HIST_UNDOSTAT視圖) 的 tuned_undoretention (該字段在10G版本才有,9I是沒有的)字段可以得到Oracle
根據事務量(如果是文件不可擴展,則會考慮剩余空間)采樣后的自動計算出最佳的 retenton 時間.。這樣對於一個事務量分布不均勻的數據庫來說,,
就會引發潛在的問題--在批處理的時候可能 Undo 會用光, 而且這個狀態將一直持續, 不會釋放。

查詢tuned_undoretention:
select to_char(begin_time,'DD-MON-RR HH24:MI') begin_time,to_char(end_time,'DD-MON-RR HH24:MI') end_time,tuned_undoretention from v$undostat order by end_time;

檢查一天平均每秒產生的UNDO BLOCK
select (sum(undoblks)/sum((end_time-begin_time)*86400) from v$undostat;
生成的結果是UNDO BLOCK,如果需要計算出實際大小,則需要乘以db_block_size(通過show parameter db_block_size查出來)

---計算合適的UNDO表空間大小:
select (UR*(UPS*DBS))+(DBS*24) as "bytes" from (select values as UR from v$parameter where name='undo_retention'),(select (sum(undoblks)/sum(((end_time-begin_time)*86400))) as ups from v$undostat),(select values as DBS from v$parameter where name='db_block_size');
ORA-01555 When Max Query Length Is Less Than Undo Retention, small or 0 Seconds (Doc ID 1131474.1)
set pagesize 25
set linesize 100
column UNXPSTEALCNT heading "# Unexpired|Stolen"
column EXPSTEALCNT heading "# Expired|Reused"
column SSOLDERRCNT heading "ORA-1555|Error"
column NOSPACEERRCNT heading "Out-Of-space|Error"
column MAXQUERYLEN heading "Max Query|Length"
select inst_id, to_char(begin_time,'MM/DD/YYYY HH24:MI') begin_time,
UNXPSTEALCNT, EXPSTEALCNT , SSOLDERRCNT, NOSPACEERRCNT, MAXQUERYLEN, TUNED_UNDORETENTION
from gv$undostat
order by inst_id, begin_time;

 

SELECT OWNER,SEGMENT_NAME,BYTES/1024/1024 MB FROM DBA_SEGMENTS WHERE
TABLESPACE_NAME='UNDOTBS1';
SELECT * FROM DBA_ROLLBACK_SEGS;
SELECT * FROM V$ROLLNAME;
SELECT * FROM DBA_UNDO_EXTENTS;
SELECT TABLESPACE_NAME, STATUS, SUM(BYTES) / 1024 / 1024 "Bytes(M)"
FROM DBA_UNDO_EXTENTS
GROUP BY TABLESPACE_NAME, STATUS;
SELECT R.STATUS "Status",
R.SEGMENT_NAME "Name",
R.TABLESPACE_NAME "Tablespace",
S.EXTENTS "Extents",
TO_CHAR((S.BYTES / 1024 / 1024), '99999990.000') "Size"
FROM SYS.DBA_ROLLBACK_SEGS R,
SYS.DBA_SEGMENTS S
WHERE R.SEGMENT_NAME = S.SEGMENT_NAME
AND S.SEGMENT_TYPE IN ('ROLLBACK', 'TYPE2 UNDO')
ORDER BY 5 DESC;
SELECT R.NAME 回滾段名,
S.SID SID,
S.SERIAL# SERIAL,
S.USERNAME 用戶名,
S.MACHINE 機器名,
T.START_TIME 開始時間,
T.STATUS 狀態,
T.USED_UBLK 撤消塊,
USED_UREC 撤消記錄,
T.CR_GET 一致性取,
T.CR_CHANGE 一致性變化,
T.LOG_IO "邏輯 I/O",
T.PHY_IO "物理 I/O",
T.NOUNDO NOUNDO,
G.EXTENTS EXTENTS,
SUBSTR(S.PROGRAM, 1, 50) 操作程序
FROM V$SESSION S,
V$TRANSACTION T,
V$ROLLNAME R,
V$ROLLSTAT G
WHERE T.ADDR = S.TADDR
AND T.XIDUSN = R.USN
AND R.USN = G.USN
ORDER BY T.USED_UBLK DESC;

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM