天天看點

undo案列一

這周跟oracle 10g undo耗上了,一周連續遇到兩套資料庫undo表空間使用率過高的情況,表面現象基本一緻,但是實際的情況卻不同,記錄下。。。

案例一:

DB:10.2.0.2.0

OS:AIX

現象:早上一到就被客戶找到說有套庫的UNDO使用率很高(後來才知道前一天還因為undo表空間空間不足,一批處理程式報ORA-30036錯誤,沒執行成功)。

一聽到這個消息,我第一反應是問客戶是否是10g資料庫(10g資料庫因為undo_retention自動優化引起undo表空間使用率過高的情況很常見,之前也遇到過幾個這樣的案例),客戶說是10g的,慣性思維的認為是undo_retention自動優化功能引起的(有時候慣性思維也不好)。

簡單的看了下該資料庫設定的undo_retention設定為

SQL> show parameter undo

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
_in_memory_undo                      boolean     FALSE
undo_management                      string      AUTO
undo_retention                       integer     43200
           

43200/60/60 = 12個小時,算是一個比較長的時間了。

通過檢視v$undostat來檢視undo_retention優化自動調整的undo_retention時間

BEGIN_TIME          END_TIME             ACTIVEBLKS UNEXPIREDBLKS EXPIREDBLKS TUNED_UNDORETENTION
------------------- -------------------  ---------- ------------- ----------- -------------------
2013-01-08 08:05:59 2013-01-08 08:15:59     0       2368       2907672   33808        43200
2013-01-08 08:15:59 2013-01-08 08:25:59     0       2368       2827800   32784        43200
2013-01-08 08:25:59 2013-01-08 08:35:59     0       2368       2829848   31760        43200
2013-01-08 08:35:59 2013-01-08 08:45:59     0       3392       2841368   32528        43200
2013-01-08 08:45:59 2013-01-08 08:55:59     0       3392       2846488   30480        43200
2013-01-08 08:55:59 2013-01-08 09:05:59     0       6464       2853656   26384        43200
2013-01-08 09:05:59 2013-01-08 09:15:59     0       4416       2880280   31504        43200
2013-01-08 09:15:59 2013-01-08 09:25:59     0      11584       2885400   20240        43200
           

檢視undo表空間extent的情況

SQL> select status,sum(bytes)/1024/1024 mb from dba_undo_extents group by status;

STATUS            MB
--------- ----------
EXPIRED    21350.625
UNEXPIRED  1488.1875
ACTIVE             8
           

從上面的情況來看,确實是undo_retention時間比較長引起。

建議客戶通過設定_undo_autotune為false來關閉undo_retention的自動優化功能,設定undo_retention為10800。

設定後讓客戶重新跑程式,結果到中午的時候發現undo 中active狀态的extent持續增加,undo表空間又即将不足,又緊急擴容8G,難道是真的由于undo不足,經熊哥(O(∩_∩)O哈!,大牛老熊)指點,發現些線索。下面是前一天undo運作的情況:

BEGIN_TIME          END_TIME            SSOLDERRCNT NOSPACEERRCNT ACTIVEBLKS UNEXPIREDBLKS EXPIREDBLKS
------------------- ------------------- ----------- ------------- ---------- ------------- -----------
2013-01-07 13:45:59 2013-01-07 13:55:59           0             0    1646136        142360      131488
2013-01-07 13:55:59 2013-01-07 14:05:59           0             0    1740112        127328       52288
2013-01-07 14:05:59 2013-01-07 14:15:59           0             0    1834240         81264        4352
2013-01-07 14:15:59 2013-01-07 14:25:59           0             0    1909856          9728         400
2013-01-07 14:25:59 2013-01-07 14:35:59           0             0    1910088          8864         344
2013-01-07 14:35:59 2013-01-07 14:45:59           2             4    1909032         10824         128
2013-01-07 14:45:59 2013-01-07 14:55:59           2             1    1908616         11352          16
2013-01-07 14:55:59 2013-01-07 15:05:59           0             1       3424       1916552           8
2013-01-07 15:05:59 2013-01-07 15:15:59           0             0       3656       1915664         664
2013-01-07 15:15:59 2013-01-07 15:25:59           0             0       2752       1915000        2232
2013-01-07 15:25:59 2013-01-07 15:35:59           0             0       3776       1906608        1792
           

在1月7日下午14:35到15:05之間NOSPACEERRCNT字段開始出現計數(計數總共6次),該字段表示請求undo空間未成功的次數,在14:35到14:45期間undo表空間使用的空間為active狀态的extent為1908616*8192/1024/1024=14911(MB)、unexpired狀态的extent為11352*8192/1024/1024=89(MB),合計15G,此次資料庫PSAPUNDO表空間的大小也為15G,已沒有空閑空間可配置設定(詢問客戶,這跟前程式報錯的時間基本一緻),随後的時刻active狀态的extent降為3424*8192/1024/1024=27(MB),unexpired狀态的extent增加為1916552*8192/1024/1024=14973(MB).

随後客戶先擴容了8G,再看看擴容後的情況

BEGIN_TIME          END_TIME            SSOLDERRCNT NOSPACEERRCNT ACTIVEBLKS UNEXPIREDBLKS EXPIREDBLKS
------------------- ------------------- ----------- ------------- ---------- ------------- -----------
2013-01-07 22:55:59 2013-01-07 23:05:59          0             0    2940528          3320            0
2013-01-07 23:05:59 2013-01-07 23:15:59          0             0    2940520          3296           32
2013-01-07 23:15:59 2013-01-07 23:25:59          0             0    2940520          3296           32
2013-01-07 23:25:59 2013-01-07 23:35:59          0             0       2376       2941288          184
2013-01-07 23:35:59 2013-01-07 23:45:59          0             3       2392       2941448            8
2013-01-07 23:45:59 2013-01-07 23:55:59          0             0       2368       2940888          592
           

在23:15到23:25之間,active狀态的extent為2940520*8192/1024/1024=22973(MB),unexpired狀态的extent為26(MB),合計23G左右,此時已沒有空閑空間可配置設定,客戶确認在此期間運作的批處理程式确實再次報錯ORA-30036。

可以确定該批量程式需要的undo表空間的使用率确實超過undo自身的空間。

總結下:

出現ORA-30036報錯的情況(目前能想到的):

1)undo_retention設定時間過大,導緻undo中配置設定的大部分extent長期處于unexpired狀态,影響extent的回收重用。

2)oracle 10g的新特性undo_retention自動優化功能根據undo的使用情況,自動計算出undo_retention的值,導緻大部分extent長期處于unexpired狀态,影響extent的回收重用。

3)undo表空間自身設定得過小,且置于非自動增長模式下,也會導緻該錯誤的發生。

4)有過大的事務,其需要的undo空間大于目前資料庫undo表空間的空間

5)Oracle的BUG。Bug:5387030 - Automatic tuning of undo_retentioncauses unusual extra space allocation [ID 5387030.8]

6) Oracle在undo_retention自動優化管理方面的缺陷。

順帶學習了下Oracle在undo表空間自動管理模式下,請求空間的情況如下:

當一個新事務開始,按以下步驟進行:

1) 在沒有active transaction的undo segment上配置設定一個extent,oracle盡可能将事務分布在所有的undo segment上。

2) 如果沒有找到online的segment,則嘗試去找offline的segment,并online它。

3) 如果沒有找到,則建立一個新的undo segment.

4) 如果空間不允許,在目前的undo segment上嘗試重用expired狀态的extent.

如果一個已經運作的事物,需要更多的undo空間時,執行以下步驟:

1) 如果目前的extent有free block,則使用它們。

2) 如果目前的extent沒有free block,并且下一個exent是expired狀态,則使用下一個extent.

3) 如果下一個extent不是expired狀态,那麼嘗試從undo tablespace擷取空間,如果有空閑空間,則為目前的segment配置設定新的extent.

4) 如果沒有空閑空間,需要從offline segment上偷extent,先從offline segment上deallocate extent,然後加到目前的undo segment上。

5) 如果沒有offline segment,則從online segment上偷extent,同樣從online segment 上deallocate extent,然後加到目前的undo segment上。

6) 嘗試擴充資料檔案。

7) 嘗試重用目前undo segment上unexpired狀态的extent,如果所有的exetent都繁忙(包含未送出的事務),則下一步。

8) 嘗試從offline的segment上偷取unexpired狀态的extent

9) 嘗試從online的segment上偷取unexpired狀态的extent

10)如果以上步驟都無法擷取空間,則報錯ORA-30036:unable to extend segment by %s inundo tablespace ‘%s’

參考資料:http://www.hellodb.net/2009/02/oracle_undo.html