老白對於RAC應用調優的建議--(摘自老白的ORACLE RAC 日記)

y81277241發表於2014-11-13
雖然ORACLE的售前人員總是說RAC的擴充套件性是透明的,只要把應用分到不同的節點,就可以平滑的擴充套件系統能力了。
而事實上,RAC的CACHE FUSION機制決定db cache,library cache等在RAC環境下都會由於CACHE FUSION而帶來
額外的開銷。
    在一個單例項環境中,如果我們要訪問某個Cache buffer,我們只需要閂住相關的cache buffer chains,然後
去讀取這個buffer就行了,而在RAC環境中,首先我們要閂住cache buffer chains,檢視該buffer的當前版本是否
在這個例項的db cache中,如果沒有找到,那麼就要發出訊息詢問其他的節點,是否cache 在其他節點中存在,如果存在
,那麼就要從其他節點透過網路將這個buffer 傳輸過來。
 
在一個單例項的環境中,db cache的命中率 96% 和 97% 可能對系統影響不大,而在RAC環境中,db cache 命中率下降一個百分點,對於系統效能造成的總體影響要大上數倍。因此在設計RAC應用的時候,如何減少CACHE FUSION帶來的負面影響是十分關鍵的。在一個RAC環境中,沒有任何資料共享是不可能的,或多或少都會有資料共享,因此如何在例項之間共享資料是解決RAC應用效能問題的關鍵。


在國內的應用設計方面,為了避免 CACHE FUSION使用最廣的方法是應用隔離,也就是在RAC的不同節點上跑不同的應用,從而最大幅度的減少資料的共享。應用隔離確實是一種很好的RAC應用最佳化方案,實施起來也比較簡單,不需要十分專業的RAC最佳化技術。不過應用隔離雖然實施難度較小,也被使用比較廣泛,但是應用隔離是RAC最佳化中最為低階的應用層次,在很多情況下,某個應用主要集中在某幾張表的訪問,這樣想要做的應用隔離的難度較大,在這種情況下,需要對應用做更為細緻的最佳化。就像老白處理的這個案例,在兩個節點要跑完全相同的應用,這種情況下的最佳化,就需要從應用底層開始設計了。從總體上來說,減少CACHE FUSION帶來的效能影響的方法有一下幾個方面。

1>透過表分割槽來限制某個分割槽被某個例項使用。對於RAC應用來說,表分割槽是很好的減少熱塊爭用的手段。首先透過表分割槽,使資料分散到數個segment中,其高水位推進,資料訪問等都被分散了。因此在RAC環境中設計表分割槽的時候也要注意,表分割槽逐漸的選擇確實能夠起到分散資料分佈的作用。如果我們有一張日誌表,根據日誌的日期進行分割槽,那麼雖然我們做了分割槽,但是還是無法起到分散資料訪問的作用,因為我們總是在最新的那個分割槽裡插入和查詢資料,其他分割槽很少會被訪問到。

2>增加db cache的命中率。在一般的OLTP系統中,db cache命中率超過90%就不算太低了,如果超過95%那就說明db cache的命中率比較高了。但是在RAC環境中,db cache的命中率越低,CACHE FUSION帶來的負面影響就越大,因此在RAC環境下,保持較高的db cache命中率對於系統總體效能大的影響十分巨大。

3>增加共享池的命中率。在RAC環境中,SQL的分析等操作要比單機環境昂貴的多,主要原因是分析等操作涉及大量的全域性資源的協同。在RAC環境中減少硬分析、軟分析等也有十分重要的意義。因此保持較為充足的共享池資源,使用好的程式設計習慣,合理使用繫結變數等都有助於提高RAC環境下的系統效能。

4>加大sequence 的 cache,並使用noorder選項。在RAC中經常會遇到SQ鎖等待,這是因為在RAC環境下,sequence也成為全域性性的了,不同節點要生成序列號,就會產生對sequence資源的爭用。而目前大多數系統中,sequence大多數被作為主鍵發生器來使用,使用的頻率十分高,在RAC環境中,需要設定較大的 sequence cache,否則會造成較為嚴重的爭用,從而影響業務。


另外在業務允許的情況下,sequence 儘可能使用noorder選項,從而減少sequence 產生器的負擔。對於十分嚴重的sequence爭用,甚至有使用者使用UUID來替代sequence.UUID是一個37位字串,透過生成機制來確保全域性唯一性。這個特點也可以用來作為主鍵使用。在Oracle中,可以透過 select sys_guid() from dual來生成一個UUID,這個UUID是不帶“-”的,所以只有32位。

|||||||||||||||||||
關於enqueue的一個案例
平均事務響應時間在200毫秒左右,IO基本上很空閒,兩個節點的CPU使用率比較低,基本穩定在30%左右。從主要等待事件上看,global cache cr request、db file sequential read和enqueue排在前三位。enqueue等待大概佔整個等待事件的13%左右。我馬上開啟了enqueue的圖表,發現排在第一位的enqueue是SQ。透過指令碼檢查v$enqueue_stat:

SELECT eq_type,cum_wait_time
from v$enqueue_stat
order by 2;
從查詢結果上來看,排在前三位的是SQ、US和TX。SQ排在第一位肯定是sequence存在較為嚴重的衝突。我做了一個statspack報告,從Statspack報告中可以看出row cache objects相關的等待還是比較多的,從row cache的情況看,dc_sequence的等待和丟失率也比較高。於是我檢查了一下sequence的引數,所有的sequence cache引數都是預設的20。於是我讓秦工儘快聯絡開發人員,重建所有的sequence,將sequence 的cache引數都加大為1000。


隨著系統負載的增加,CPU的使用率也提高了40%以上,global cache相關的等待事件和enqueue等待也比剛才多了一些。突然整個系統出現了異常,平均事務響應時間出現了一個突變,提高了一倍多,好像出現了短暫的HANG住現象。我看了一下OEM的健康性圖示,發現logon的指標不正常得高,在兩個節點上平均每秒logon的數量達到了30多。我問秦工是不是系統有短連線的應用。秦工說他們的系統中絕大多數都是C/S結構的,平均每秒logon的數量一直都挺高的。

看樣子我剛才又忽略了一個問題,在RAC環境下,如果logon較多的話,需要加大一個sequence的cache,剛才開發廠商已經加大了所有應用的sequence的cache,但是sys.audses$的cache卻忘記調整了,檢查了一下,確實sys.audses$的cache是預設的20.在RAC環境下,如果logon較為頻繁的話,這個sequence是必須調整的。我甚至碰到過由於logon的密度比較高,導致整個資料庫HANG住的現象。於是我建議等會調整的時候,把sys.audses$的cache調整為5000

關於sequence cache
1、Create Sequence
你首先要有CREATE SEQUENCE或者CREATE ANY SEQUENCE許可權,
CREATE SEQUENCE emp_sequence
INCREMENT BY 1 -- 每次加幾個
START WITH 1 -- 從1開始計數
NOMAXVALUE -- 不設定最大值
NOCYCLE -- 一直累加,不迴圈
CACHE 10;
||||||||||||||||||||

alter sequence sys.AUDSES$ cache 5000;


5>使用只讀表空間。只讀表空間在RAC中時十分有用的,在CACHE FUSION下,如果某個表空間是隻讀的,那麼表空間中資料的訪問只需要本地操作就可行了,不需要RAC間協同。實際上,很多資料庫中的資料,在某個時間段裡都會有大量的只讀資料,這些資料如果訪問十分頻繁,
那麼在RAC下就會對GES和GCS產生很嚴重的影響。實際上,如果我們在設計應用系統的時候就充分考慮了RAC的問題,完全可以把可能只讀訪問或者在某個時間段內只讀訪問的資料放在相同的表空間中,這些資料可以根據業務需要設定為讀寫或者只讀。比如,老白曾經給一個客戶做過最佳化,他們系統中的歷史資料訪問十分頻繁,老白建議他們把歷史資料存放在單獨的表空間中,平時設定為READ ONLY,只有做資料歸檔的時候才改回READ WRITE。透過這個簡單的最佳化動作,減少了大量的全域性訪問,改善了RAC的效能。


6>減少大表的全表掃描。全表掃描特別是大表的全表掃描,對 db cache的影響十分巨大,由於全表掃描會佔用大量的db cache,這樣就會把很多DATABLOCK 從 db cache中擠出去,而且大表的全表掃描會帶來大量的物理讀,在RAC環境中,物理讀的開銷遠大於單機環境。


7>限制並行查詢在例項範圍內,不要再RAC例項之間做並行查詢。實際上,絕大多數的並行查詢並不需要跨例項執行,而Oracle 預設情況下並行查詢是跨例項的,所以很多客戶都吃過這個苦頭,跨例項做並行查詢主要是解決單機CPU能力不足的問題,但是跨例項並行查詢會引起GCS方面的問題。目前國內使用者系統的單機CPU能力一般都比較強,因此使用跨例項並行查詢往往得不償失。Oracle在RAC下的並行查詢方面的配置十分靈活,透過設定instance_groupsparallel_instance_group引數就可以實現靈活的策略,透過配置這兩個引數,可以輕鬆實現將並行查詢限制在本機上。

|||||||||||||
案例
在監控過程中,我們發現了大量的PX等待事件,這是由於這個系統中存在大量的統計模組,這些模組做了大量的PX等待事件,這是由於這個系統
中存在大量的統計模組,這些模組做了大量的全表掃描,為了提高全表掃描的效能,在很多SQL中,加了PARALLEL提示。我檢查了一下並行查詢,
發現存在不少跨例項的並行查詢。為了防止不必要的問題,建議一般情況下並行查詢限制在例項內,這可以透過instance_groups引數來實現:
Rac1.Instance_groups=rac1,rac
Rac1.Parallel_instance_group=rac1
Rac2.Parallel_instance_group=rac2
Rac2.Instance_groups=rac2,rac
透過這些引數的設定,在預設的環境下,並行查詢只能在例項內進行。因為每個例項的預設parallel_instance_group都是例項名,只有本例項
的instance_group引數中包含和本例項名相同的instance_group。而如果想要某個SQL跨例項做並行查詢時,可以透過下面的方法進行:
alter session set parallel_instance_group=rac;
Select ...
由於兩個例項都屬於RAC instance_group,所以只要把parallel_instance_group設定為"rac“就可以了。

在我碰到的RAC系統中,大多數CPU的使用率都不高,


||||||||||||||||||||||

8>透過應用隔離,在每個例項上跑不同的應用。RAC每個節點跑不同的應用是目前國內RAC系統中很常用的一種方法,通常被稱為應用隔離。應用隔離室RAC應用最佳化中最為初級的形態,不過也是較為有效的形態。在這種模式下,多個應用共享非關鍵資料,核心業務資料的關聯度較小,透過將不同應用分佈在不同的例項上,確保RAC的各個例項間共享的資料較少,訪問衝突限制在一個可控的範圍內。

9>資料的橫向隔離。應用隔離室較為初級的最佳化形態,雖然有效但是有很多限制,比如某個應用十分龐大,一個單節點無法承擔,那樣就無法透過應用隔離的方式來最佳化了。這種情況下,資料的橫向隔離就十分有效了。以電信業務為例,其核心業務資料如果能夠按照本地網進行分割槽,那麼我們就可以設定部分本地網的應用連線在例項1上,部分本地網應用連線在例項2上。透過表分割槽來確保核心業務(p221 寫錯了)資料之間的衝突降到最小,從而避免由於RAC中資料塊爭用帶來的問題。。

|||||||||||||
案例
第一輪測試已經接近尾聲了,我檢查了一下enqueue的情況,發現了一個奇怪的現象,有不少TX鎖等待的request都是4,這是典型的ITL等待。在RAC環境下,ITL等待的危害性遠遠高於普通環境。檢查了一下,發現這些ITL等待都集中了在3-4張表上,這些表的規模並 不大,都是100-200MB,不過這些表的併發修改十分大。我檢查了一下,INITTRANS引數都是預設值,這就難怪了。於是我和秦工決定對所有的表做一個檢查,把一些併發修改較多的表INITTRANS引數都加大,這個操作還需要一些時間,因此在第二次壓力測試之前就無法實施了。

實際的命令是?

DROP TABLE CX.CX CASCADE CONSTRAINTS;

CREATE TABLE CX.CX
(
  NAME  VARCHAR2(20 BYTE),
  AGE   NUMBER
)
TABLESPACE CXTEST
PCTUSED    0
PCTFREE    10
INITRANS   5
MAXTRANS   255
STORAGE    (
            INITIAL          64K
            MINEXTENTS       1
            MAXEXTENTS       UNLIMITED
            PCTINCREASE      0
            BUFFER_POOL      DEFAULT
           )
LOGGING
NOCOMPRESS
NOCACHE
NOPARALLEL
MONITORING;


ALTER TABLE CX.CX INITRANS 8;

|||||||||||

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

相關文章