性能分析之子鎖存器到SQL
這幾天碰到一個事情,有必要記錄一下。
在一個項目中,壓力測試工具中一個業務響應時間變長,資料庫(oracle)CPU使用率99%以上。
從AWR報告上看到如下信息:
在性能項目的溝通中,經常是在這樣的時候,我們就去告訴開發說現在的狀態是CPU使用率高,把AWR報告往開發那裡一發,性能團隊的人員就喝咖啡去了。
但是性能如果只是做到這裡,溝通其實沒有在同一個界面上。
在這個典型的溝通過程中,上述結果也確實發給開發了。
開發反饋說,是因為在場景執行過程中表的數據量發生了變化,導致了SQL的執行計劃發生了變化,進而導致了SQL慢,進而導致了latch: cache buffers chains的出現。所以要解決的話,要對資料庫進行一次analyze,然後再測試。
在上述的背景中,看似沒有漏洞,合情合理。
但是,
恰好碰到我這偏執的人,我要看到證據鏈。
在溝通的來往中,我並沒有看到證據鏈,這是我覺得不好的地方。哪裡沒有證據呢?就是數據量發生了變化導致了SQL的執行計劃發生了變化。
如果有這樣的懷疑,就要去證明這個懷疑是對的。
於是我查了SQL計劃的歷史變更記錄。
根據SQLID查看執行計劃的變更記錄:
selectDISTINCTSQL_ID,PLAN_HASH_VALUE,TO_CHAR(TIMESTAMP,"yyyymmdd hh24:mi:ss")TIMESTAMPfromdba_hist_sql_planwheresql_id="1wfsd2q8wc5uu"orderbyTIMESTAMP;
SQL_ID PLAN_HASH_VALUE TIMESTAMP
查詢更詳細的執行記錄變更記錄(我把結果中的時間戳刪掉了,為了格式整齊點):
selectplan_hash_value,id,operation,options,object_name,depth,cost,TO_CHAR(TIMESTAMP,"yyyymmdd hh24:mi:ss")fromdba_hist_sql_planwheresql_id="1wfsd2q8wc5uu"andplan_hash_valuein(4188019746)orderbyID,TIMESTAMP;
PLAN_HASH_VALUEIDOPERATIONOPTIONSOBJECT_NAMEDEPTHCOST
這個SQL的執行計劃,只有4月1日一條記錄,在最近幾天的測試中,並沒有發生變更。
這就是我要說的證據鏈,當給出執行計劃發生變化這個結論時,就必須給出證明,而實際的數據證明這個結論是錯的。
下面我們就來分析下怎麼才是對的。
既然是latch: cache buffers chains,首先我們得知道這個值是什麼意思。
簡單回憶下latch的原理(如下部分是在網上抄的):
當一個數據塊讀入到SGA中時,該塊的塊頭(BUFFERHEADER)會放置一個HASHBUCKET的鏈表(HASHCHAIN)中。該內存結構由一系列cachebuffers chains的子latch保護。對BUFFERCACHE中的塊,要SELECT/UPDATE/INSERT/DELETER等操作都得先獲得cachebuffers chains的子latch,以保證對CHAIN的排他訪問。若在過程中發生爭用,就會出現latch:cache buffers chains事件。
這個值的出現有兩個含義:
SQL的執行效率低:因為SQL低效,在並發會話時,無法得到相同的數據集,SQL執行時帶有高BUFFER_GETS會導致latch爭用。
數據熱塊。
這是兩個完全不同的處理方向。
第一個處理方向,考慮到近期場景執行得比較頻繁,資料庫變更較多,所以先把資料庫做個整體的分析,再來測試下。經過證明之後,發現果然分析了整庫之後,時間刷刷的降低了很多,然後就把存儲的IO壓到80%以上了。
雖然開發說執行計劃變更是錯的,但是分析整庫的處理方法是對的。
套用大話西遊里說的:我猜中了結尾,但是沒有蒙對過程。
看到這裡,是不是覺得問題解決了?可以收工了?很開心的喝咖啡去了?
但是,我又偏執了。我考慮了下參數化的邏輯,我覺得數據熱塊應該是存在的。現在之所以沒有暴露出來,是因為IO跟不上了。所以我要判斷下,如果IO夠用的話,熱塊會不會成為下一個瓶頸。於是,接著查。
先看看爭用是否嚴重:
selectround((misses / gets) *100) ||"%",
round(100* immediate_misses /(immediate_gets + immediate_misses))||"%"
fromv$latch
wherename="cache buffers chains";
round((misses / gets) *100) ||"%"的值是3%。可見還是有一些熱度的。
再來查下子鎖存器視圖,看是否有熱塊。看看傾斜度。
select*from(selectaddr,child#,gets,misses,sleepsfromv$latch_childrenwherename="cachebuffers chains"orderbysleepsdesc)whererownum
傾斜度是有的。再看下對象的熱度:
selecthladdr,
obj,
(selectobject_name
fromdba_objects
where(data_object_idisnull
andobject_id = x.obj)ordata_object_id = x.objandrownum=1)asobject_name, dbablk, tch
fromx$bh x
orderbytchdesc;
TCH是touch count,此值越高,則熱度越高。
查找引起熱塊的SQL。
select*
from(selectcount(*),
sql_id,
nvl(o.object_name, ash.current_obj#) objn,
substr(o.object_type,,10) otype,
CURRENT_FILE# fn,
CURRENT_BLOCK# blockn
fromv$active_session_history ash, all_objects o
whereeventlike"latch: cache buffers chains"
ando.object_id(+) = ash.CURRENT_OBJ#
GROUPBYSQL_ID,
current_obj#,
current_file#,
current_block#,
o.object_name,
o.object_type
orderbycount(*)desc)
whererownum
根據SQLID查一下SQL的文本,果然就是我們用到的那個查詢業務SQL。
在性能分析中,我們太容易給自己定個範圍或圈套了。有時覺得這個事情不該是自己做的。
如果單從職場的角度說,這樣想並無不妥。
但是如果從技術角度說,這樣想就必然會導致自己的能力受限。
所以不用給技術下個定義,在個人能力能達到的地方,都盡量去做,學無止境。
而從現象到瓶頸的性能分析是最需要一個人有足夠的知識寬度的,因為你不知道在尋找瓶頸的過程中會遇到什麼樣的知識弱點。
今天碰到的是oracle,明天碰到mysql、HBase怎麼辦?啥也別想,二話不說,辦它就對了。
TAG:7DGroup |