RAC遇到GC Buffer Busy的解決方法2

531968912發表於2016-07-12

inst_id分割槽避免rac gc buffer busy

透過ASH報告,我看到剛才系統HANG住的時候,主要的等待事件是buffer busy wait

Avg Active

Event Event Class % Activity Sessions

----------------------------------- --------------- ---------- ----------

buffer busy waits Concurrency 72.55 9.31

enq: HW - contention Configuration 14.21 1.82

gc buffer busy Cluster 7.67 0.98

CPU + Wait for CPU CPU 2.13 0.27

-------------------------------------------------------------

看樣子是由於熱塊衝突導致系統HANG住的,而且高水位推進相關的鎖等待也很嚴重,應該系統中有大量的資料插入。從這個情況看想簡單的透過調整引數來解決問題是不大可能,必須從應用的特點去分析,才有可能找到解決方案。於是我問郝經理:"你的應用是什麼樣的,是不是有大量的插入操作?"

郝經理告訴我這個系統是企業應用整合系統,是從其他系統中接收資料,經過處理後儲存在本系統中,供經營分析系統使用。目前的壓力測試中的主要操作是對34張大表進行大批次的資料插入,其中還有張表裡帶LOB欄位。

我和郝經理研究了一下,對這些資料的訪問,除了大規模的資料插入外,一般來說是按主鍵訪問,或者按某些分類條件的小範圍查詢,每次範圍查詢頂多佔整個表資料量的幾萬分之一,並且範圍查詢的比例相對較小,僅佔整個系統查詢數量的10%不到。這種情況是典型的可以使用HASH分割槽的,透過HASH分割槽既可以解決BUFFER BUSY WAIT的問題,又可以解決enq: HW -contention的問題。於是我建議郝經理把這幾張表按照主鍵MSG_IDhash分割槽,先嚐試一下16個分割槽,看看能不能解決問題。

按照我的建議做了HASH分割槽後,壓力測試重新開始了,這回看樣子效果很不錯,從em控制檯上看,buffer busy wait等待已經少了很多,而且enq: HW - contention等待也消失了。


Avg Active

Event Event Class % Activity Sessions

----------------------------------- --------------- ---------- ----------

gc buffer busy Cluster 90.69 14.83

gc current request Cluster 6.05 0.99

CPU + Wait for CPU CPU 1.05 0.17

目前的主要等待是gc buffer busy,由於目前在連個節點上各有40個併發插入的會話在進行資料插入,因此全域性BUFFER等待的問題肯定是存在的,目前壓力測試已經進行了1個多小時了,從em觀察到的情況來說系統一直還很平穩。現在的時間已經是中午的12點半了,郝經理建議我們先去吃飯,等吃完飯回來再看看結果。

在下面的食堂裡簡單吃了點東西,我們就回到了辦公室,現在是下午的1320分了,壓力測試也已經開始了差不多2個小時了,系統的狀態依然和我們吃飯前一樣,還沒有出現hang住的現象。不過從平均事務響應時間來看,現在比一個小時前要慢了40%,這是一個十分不好的現象,如果這種趨勢延續下去的話,很可能會再次出現系統HANG住的現象。

看著郝經理他們興奮的樣子,我給他們潑了盆冷水,可能問題還是沒徹底解決,從目前的趨勢上看,有可能系統還會HANG住。我正在和他解釋為什麼我會有這種預感,突然從EM上看到系統活躍情況突然下降了,系統可能又HANG住了。

我連忙做了一個3級的hanganalyze,從trace上看:

Open chains found:

Chain 1 : <cnode/sid/sess_srno/proc_ptr/ospid/wait_event> :

<0/786/9/0xff010e58/9474/gc buffer busy>

-- <0/785/26/0xff011e38/9512/gc current request>

Chain 2 : <cnode/sid/sess_srno/proc_ptr/ospid/wait_event> :

<0/791/32/0xff00e6a8/9404/gc buffer busy>

-- <0/785/26/0xff011e38/9512/gc current request>

Chain 3 : <cnode/sid/sess_srno/proc_ptr/ospid/wait_event> :

<0/792/12/0xff00ee98/9408/gc buffer busy>

-- <0/785/26/0xff011e38/9512/gc current request>

Chain 4 : <cnode/sid/sess_srno/proc_ptr/ospid/wait_event> :

<0/794/19/0xff00d6c8/9334/gc buffer busy>

-- <0/785/26/0xff011e38/9512/gc current request>

大量的gc buffer busy導致了大量的gc current request等待。很多會話由於gc buffer busyHANG住一段時間,實際上系統並沒有真正的HANG住,而是變得十分慢而已。不過如果這種情況的範圍如果擴大的話,就會導致應用軟體出現問題,產生丟失資料的現象。過了幾分鐘,郝經理那邊也確認了這次系統HANG住,1號節點的應用被掛起了35秒鐘,丟失了70多條資料,實驗再次失敗了。

看樣子GC BUFFER BUSY最終還是導致了嚴重的問題。由於他們的應用沒有針對RAC進行最佳化,同一個應用分別在2個節點上跑,所以導致了嚴重的節點間的熱塊衝突。也許把這個應用集中在一個節點上就能夠解決問題。我把我的想法和郝經理說了,郝經理覺得可以試試,不過他們的系統發展起來特別快,所以從最初做設計的時候就考慮要使用RAC,而且今後不僅要支援雙節點,還可能擴充套件為3節點甚至4節點。目前的業務有可能單節點能夠支援,不過今後一個節點可能無法支撐所有的負載。

我考慮了一下,剛才應用放在兩個節點上跑的時候,兩個伺服器的CPU使用率都已經超過60%了,如果跑在一個節點上,確實負載挺大的,一個節點還真有可能支援不了,更不要說今後系統擴充套件性的問題了。看樣子必須從底層結構上進行調整了。我問郝經理,如果在表裡面加一個欄位,並且每次插入的時候給這個欄位賦一個常量,這樣修改程式他們的工作量大不大。郝經理想了想說應該問題不大,修改一下也就是10分鐘的事情。

我說如果這樣就好辦,我們可以對錶結構做一個調整,來徹底解決這個問題。我們重新對錶進行分割槽,使之成為一個複合分割槽表,在這張表上加入一個欄位inst_id,也就是例項編號,這個欄位作為主分割槽欄位,按照這個分割槽做範圍分割槽後,再設定msg_idhash分割槽。調整後的表結構如下:

CREATE TABLE QSTORE

(

MSG_ID VARCHAR2(64 BYTE) NOT NULL,

DOCE_ID VARCHAR2(100 BYTE) NOT NULL,

DOC_KEY VARCHAR2(100 BYTE) NOT NULL,

BUS_NAME VARCHAR2(100 BYTE),

MODULE_NAME VARCHAR2(100 BYTE),

CATEGORY VARCHAR2(64 BYTE),

SUB_CATEGORY VARCHAR2(64 BYTE),

DOC_SIZE NUMBER(11) DEFAULT 0,

CREATE_TIME DATE,

MODIFY_TIME DATE,

EXPIRED_TIME DATE,

DOC_FLAG NUMBER(2),

Inst_id number

) initrans 20 pctfree 20 tablespace TS_DATA_EAI

PARTITION BY RANGE(inst_id)

SUBPARTITION BY HASH(msg_id) SUBPARTITIONS 8

(PARTITION p1 VALUES LESS THAN (2),

PARTITION p2 VALUES LESS THAN (3));;

Inst_id的值就是插入程式連線到的例項的ID,這樣調整後,在1號節點上插入的資料將全部被插入到inst_id=1的分割槽,插入操作就不會產生大量的global cache request了。這種做法也是在RAC上解決GC BUFFER BUSY的常用方法之一。

郝經理很快就明白了我的意思,上樓去安排開發人員修改應用了。我也趁機休息休息,準備下面的測試了。這時候老儲的電話又打了進來,那個問題終於解決了,透過hcheck對資料字典進行檢查,發現有一張表的資料字典出現了不一致,在tab$中還有記錄,但是在obj$裡的記錄缺失了,查詢這個表空間中有什麼物件找不到,但是刪除tablespace的時候又刪除不了。把tab$中的資料手工刪除後,表空間就成功的刪除了。

剛和老儲通完電話,郝經理的電話就打了進來,他說應用已經修改好了,他已經開始了測試,大概10分鐘後壓力就會載入到資料庫上,讓我監控一下有沒有什麼問題。從測試剛開市的情況看,gc buffer busy基本上消失了,系統也比較平穩,從EM的監控情況來看,系統一切都很平穩,系統已經執行了一個多小時,從awr報告來看,現在的平均事務響應時間,和系統剛剛啟動時差別不大,並且gc buffer busy 等待事件也已經不在top 5等待時間裡了。看樣子透過這麼最佳化,系統趨於穩定了。郝經理建議我們先回去,壓力測試做一晚上,明天上午10點再來看結果。如果那時候發現系統一切正常,那麼說明問題已經解決了。

select t.INSTANCE_NUMBER into p_inst_id from v$instance t

透過procedure進行插入,在執行的開始,取得instance_id

本文轉自:http://yu85910.blog.china.com/200903/4504368.html

gc buffer busy: 產生這個等待事件是由於例項間產生熱塊爭用造成的,要解決這個問題有兩種方法:

第一、分割應用:把應用集中在一個節點上執行

第二、對錶新增一個欄位,這個欄位存放例項的id號,如果在節點1執行的那麼存放節點1的例項id號, 如果在節點2執行的那麼存放節點2的例項id,在執行之前首現獲取例項的id號。

[@more@]

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

相關文章