Oracle Undo表空間使用情況分析 - 11gR2


環境介紹

操作系統: AIX 7.1

數據庫:Oracle 11.2.0.4

 

一般情況下,收到Undo表空間報警基本都是忽略的,因為大部分統計Undo使用率的SQL都是把UNEXPIRED部分算作已使用部分的,實際上其中有較大部分是可以重用的。

這兩天持續報Undo表空間剩余可用空間低於1%,所以查看了一下原因。

查詢SQL語句:

SQL> select tablespace_name, status, sum(bytes/1024/1024) "MB"
from dba_undo_extents
group by tablespace_name, status
order by 1, 2;

不同狀態的含義:

ACTIVE :有活動事務在使用 Undo,這部分空間屬於Session正在使用的空間;

UNEXPIRED :事務提交並且沒到undo_retention設置時間之前,這些Undo Block還沒有過期,但是已經沒有活動事務在使用了,在超過undo_retention設置時間之后,這部分空間會變成EXPIRED狀態;

EXPIRED :事務提交並且到undo_retention設置時間之后,這些Undo  Block已經過期了,這部分空間是可以重用的,屬於未使用空間;

可以看到 ACTIVE和UNEXPIRED的大小達到98272 MB(UNDOTBS1表空間大小98296 MB),使用率接近100%。

查找資料發現Oracle 10g中引入了一個新的自動調整undo_retention的特性,在Oracle Database 10g中當自動undo管理被默認啟用,每隔10分鍾會自動設置當前的undo_retention,Oracle Database嘗試至少保留舊的undo信息到該時間。該信息可以在視圖v$undostat查到。

SQL> select begin_time,tuned_undoretention from V$UNDOSTAT where rownum < 11;

BEGIN_TIME                TUNED_UNDORETENTION
------------------------------  -------------------
2021/09/23 09:53:51       653881
2021/09/23 09:43:51       654763
2021/09/23 09:33:51       654644
2021/09/23 09:23:51       654513
2021/09/23 09:13:51       654883
2021/09/23 09:03:51       654863
2021/09/23 08:53:51       651826
2021/09/23 08:43:51       655097
2021/09/23 08:33:51       655045
2021/09/23 08:23:51       654809
2021/09/23 08:13:51       654226

可以看到Oracle設置的undo_retention時間高達65W多,所以導致出現大量的UNEXPIRED占用。

 Metalink里有一篇文章介紹Automatic Tuning of Undo Retention引起空間問題的文章:

 Automatic Tuning of Undo_retention Causes Space Problems [ID 420525.1]

 文章里給出了3個解決方法:

1)設置Undo數據文件為可擴展並且MAXSIZE為數據文件當前大小;

SQL> alter database datafile ‘<datafile_flename>’ autoextend on maxsize <current_size>;

感覺這個設置就是為了讓Automatic Tuning of Undo Retention能更准確的估算v$undostat.tuned_undoretention的大小,但是發現好像不是太管用,至少沒有立竿見影。

2)設置隱藏參數_smu_debug_mode

SQL> alter system set "_smu_debug_mode" = 33554432;

設置這個之后v$undostat.tuned_undoretention會取(maxquerylen secs + 300)和參數undo_retention里的最大值。網上有人設置之后出現大量ORA-01555錯誤,遂放棄這個方法。

3)設置隱藏參數_undo_autotune

SQL> alter system set "_undo_autotune" = false;

這個方法就比較暴力了,直接禁用了Automatic Tuning of Undo Retention特性。

4)非官方解決方法(后來再查發現也是官方建議,參考Note 742035.1)

alter system set "_highthreshold_undoretention"=86400;

在查undo相關參數的時候,發現如下參數,感覺應該有第4種解決方法:

KSPPINM                                  KSPPSTVL        KSPPDESC
----------------------------------------  --------------------  ------------------------------------------------------------
_highthreshold_undoretention  4294967294       high threshold undo_retention in seconds

測試之后,發現該參數的值可以限定v$undostat.tuned_undoretention的最大大小。

SQL> select begin_time,maxquerylen,expiredblks,unexpiredblks,activeblks,tuned_undoretention from V$UNDOSTAT where rownum < 11;

tuned_undoretention最大值限定之后,UNEXPIRED部分就開始釋放了,所以方法這個還是有效的。並且將該值限定到86400,也就是一天,應該沒有什么事務需要占用一天的Undo了,有也需要提出來優化。

SQL> select tablespace_name, status, sum(bytes/1024/1024) "MB"
from dba_undo_extents
group by tablespace_name, status
order by 1, 2;

至此,該問題解決,既使用了Automatic Tuning of Undo Retention的新特性,也不會導致Undo表空間使用率的問題。完美!

 

附錄 

Maclean博客里查詢Undo使用率的SQL

查詢undo真實的使用率:

prompt 
prompt  ############## IN USE Undo Data ############## 
prompt 

select 
((select (nvl(sum(bytes),0)) from dba_undo_extents where tablespace_name in (select tablespace_name from dba_tablespaces where retention like '%GUARANTEE' ) and status in ('ACTIVE','UNEXPIRED')) *100) / (select sum(bytes) from dba_data_files where tablespace_name in (select tablespace_name from dba_tablespaces where retention like '%GUARANTEE' )) "PCT_INUSE" from dual; 

此外,從Maclean的博客中找到兩條實用的UNDO表空間監控的查詢SQL:

--在Oracle 10g版本中可以使用V$UNDOSTAT視圖用於監控實例中當前事務使用UNDO表空間的情況。視圖中的每行列出了每隔十分鍾從實例中收集到的統計信息。

--每行都表示了在過去7*24小時里每隔十分鍾UNDO表空間的使用情況,事務量和查詢長度等信息的統計快照。 --UNDO表空間的使用情況會因事務量變化而變化,一般我們在計算時同時參考UNDO表空間的平均使用情況和峰值使用情況 --以下SQL語句用於計算過去7*24小時中UNDO表空間的平均使用量 select ur undo_retention, dbs db_block_size, ((ur * (ups * dbs)) + (dbs * 24)) / 1024 / 1024 as "M_bytes" from (select value as ur from v$parameter where name = 'undo_retention'), (select (sum(undoblks) / sum(((end_time - begin_time) * 86400))) ups from v$undostat), (select value as dbs from v$parameter where name = 'db_block_size'); --以下SQL語句則按峰值情況計算UNDO表空間所需空間: select ur undo_retention, dbs db_block_size, ((ur * (ups * dbs)) + (dbs * 24)) / 1024 / 1024 as "M_bytes" from (select value as ur from v$parameter where name = 'undo_retention'), (select (undoblks / ((end_time - begin_time) * 86400)) ups from v$undostat where undoblks in (select max(undoblks) from v$undostat)), (select value as dbs from v$parameter where name = 'db_block_size');

Automatic Tuning of Undo Retention特性介紹

Oracle 10g中引入了一個新的自動調整undo_retention的特性,其目的是為了減少ORA-01555錯誤出現的概率,Oracle會忽略UNDO_RETENTION參數設置的閥值,而是根據UNDO表空間的大小和使用率來自動調整UNDO信息的保留時間。會造成的影響是UNDO表空間的區(extent)中大部分都是未過期狀態(unexpired),這就會導致數據庫在給事務分配UNDO塊時,會優先使用UNDO表空間的的空閑空間分配,而不是覆蓋已經分配的空間,這使得UNDO表空間的使用率保持在一個較高的水平。

Oracle數據庫在為事務進行分配UNDO塊時,會按照這樣的算法和流程:
1. 如果當前區(extent)中還有空閑塊,在需要空間時會繼續使用本區(extent)中的空閑塊。
2. 在當前區(extent)使用完后,如果下一個區(extent)是過期狀態(expired),那么就跳轉到下一個區(extent)的第一個數據塊。
3. 如果下一個區(extent)不是過期狀態(expired),就從UNDO表空間申請空間,如果UNDO表空間中存在空閑的空間,就分配新的區(extent)加入到undo segment,然后跳轉到新區(extent)的第一個數據塊。
4. 如果沒有剩余空閑的區(extent),則會從OFFLINE狀態的回滾段中竊取(STEAL)過期的區,加入當前的回滾段,並使用第一個數據塊。
5. 如果OFFLINE狀態的回滾段中沒有過期的區,那么會從ONLINE狀態的回滾段竊取(STEAL)過期的區加入當前的回滾段,並使用第一個數據塊。
6. 如果UNDO表空間能夠自動擴展,則會擴展UNDO表空間,並將新區加入到當前回滾段中。
7. 如果undo表空間數據文件不能擴展,調低10%的retention值,然后竊取(STEAL)在短保留時間的過期區,如果還未找到過期區,則繼續以10%的速度減少回滾的保留時間。
8. 隨機從其他OFFLINE狀態的回滾段中竊取(STEAL)未過期的(unexpired)的區。
如果以上的嘗試都失敗,那么久會報ORA-30036錯誤。
從上面的步驟可以看出,事務會優先使用UNDO空閑空間、過期狀態(expired)的UNDO區,然后會嘗試擴展表空間的數據文件,只有在以上步驟都得不到獲得UNDO表空間后,才會去使用未過期(unexpired)的UNDO區。

引用鏈接:https://blog.csdn.net/w892824196/article/details/100123813




免責聲明!

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



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