資料庫變慢了的分析及解決辦法

楊奇龍發表於2010-06-14
        我們在日常的管理中, 經常會碰到客戶或開發人員反應速度變慢了. 這一類問題常使初級DBA摸不著頭腦, 還不如資料庫直接報出某個錯誤, 更直接了當. 下面簡單描述一下, 解決這類問題時的一般思路.
        如果有人反應速度變慢了, 最有可能影響速度的, 無外乎CPU, 記憶體和I/O. 在作業系統下,我們可以先使用top命令, 檢視一下CPU的佔用情況. 在top的輸出結果中, 特別要注意第一行中的load average, CPU的負載情況. 如果這裡顯示的數字大於CPU數, 說明CPU的負載有點高了. 再結合第三行一起看, 如果第三行中, CPU的空閒比例為0, 就說明CPU存在爭用. 正常情況下, CPU應該有一定的空閒才好. 如果這裡顯示空閒為0, 爭用CPU的不一定都是Oracle的程式. top的下面顯示的程式的列表, 只需看一下佔用CPU高的程式是否是Oracle相關的程式, 即可確認此點. 如果運氣好, 或許可以直接發現某個程式佔用了過多的CPU. 如果將問題定位到了某個程式, 對進一步解決問題, 有很大的幫助.
         但, 大多數時候, CPU的爭用已經很高了, 但是在程式列表中, 發現不了某些程式佔用過高的CPU. 這時要定位問題, 可能要複雜一些. 我們可以進入Oracle, 檢視v$sqlarea或等待事件. 在v$sqlarea檢視中, Elapsed_time和CPU_time對了解每條SQL宣告的CPU佔用情況最有幫助. 其中CPU_TIME是執行SQL宣告所耗用的CPU時間. Elapsed_time除實際耗用的CPU時間外, 還要加上等待時間.
        如果觀察V$SQLAREA沒有發現特別耗用CPU的SQL宣告. 可以在Statspace報告中對比一下正常時期的資料, 觀察一下看有沒有某條語句的CPU時間, 執行次數出現異常的變化. 有時, 或許有些SQL的CPU佔用不高, 但執行次數卻非常的高, 這也可能會成為造成CPU爭用的原兇. 解決問題時, 將問題定位的某個確定的地方, 是解決問題的第一步. 這裡, 如果可以將問題定位到某條確定的SQL, 距真正的解決問題, 就向前邁了一大步. 關於SQL宣告的調優, 可是個大問題, 這篇短短的文章很難表述清楚, 我們到以後的系列實驗中再討論.ITPUB個人空間1i)N(mSih
         在V$sqlarea檢視中,除了上面說過的Elapsed_time力CPU_time兩列外, 在瞭解某條SQL宣告的情況時,下面的這些列也很有用
      disk_reads:物理讀
      buffer_gets:邏輯讀      
      parse_calls:解析次數
      executions:執行次數      
      invalidations:無效次數
      Load:載入次數
      version_count:子游標數      
      sorts:排序次數
      sharable_mem persistent_mem runtime_mem : SQL宣告在共享池中的記憶體佔用情況.
       除了v$sqlarea檢視, 我們還可以檢視等待事件, 來了解作業系統中顯示CPU爭用時, 資料庫內部正在等待什麼, 是什麼讓Oracle的各程式忙碌不抑. statspack報告, 也可以幫助我們b瞭解這方面的資訊. 
       cpu空閒為0, 並不一定都意味著有了問題, 空閒為0, 這也說明CPU正在忙著做事情, 沒有閒在哪裡. 作業系統和資料庫總是希望CPU儘可能的繁忙, 設想一下, 如果你請了個傭人, 你也會希望他不斷的忙碌著, 不要閒在哪裡. 如果他總是閒在哪裡, 你會考慮請個傭人是不是多餘的. 但是, CPU空閒為0時, 如果同時load average中CPU的負載高於正常水平, 且有增加的跡像時, 就應該加以關注了.
        除了top外, vmstat也可以幫助瞭解cpu, 以及記憶體的情況. vmstat的第一列: r , 顯示了正在執行的和等待CPU資源的任務個數. 在CPU欄中id列, 顯示了CPU的空閒比例.  和top中的CPU負載一樣, r 列中的數字當然還是最好小於或等於CPU數
     . 除了CPU, 如果vmstat中顯示頁的交換長期不會0, 哪麼, 記憶體方面一定是出了問題. 我們可以從vmstat 的 memory欄中檢視記憶體的使用情況. 看一下free的記憶體是否小於平常的水平. Oracle中, SGA的設定不當, 或PGA的使用不當, 最易引起記憶體問題. 啟動一個Oracle會話, 使用show sga命令, 可以看到SGA所佔的記憶體數, 看這個數字沒有超過正常的水平.
       Oracle對PGA的使用, 控制比較少. 過多的連線, 過多的過大的排序, 或過大的包變數, 等等這些情況可以很容易的超PGA_AGGREGATE_TARGET的限制值. v$process中的PGA_USED_MEM(當前使用的PGA大小),PGA_ALLOC_MEM(分配的PGA大小), PGA_MAX_MEM(最大分配的PGA大小), 這幾個列可以觀察程式PGA所佔記憶體情況. 也可以在資料檢視(V$sysstat, v$sesstat, v$mystat, v$statname)中的session uga memory(會話當前所佔UGA), session uga memory max(會話曾經佔用UGA的最大數), session pga memory(會話當前所佔PGA) , session pga memory max(會話曾經佔用PGA的最大數)這幾項資料中, 觀察到會話PGA佔用記憶體情況. 
      除了vmstat外, 要觀察記憶體的使用情況, 還可以使用free命令. 在Linux和UNIX中, Oracle的SGA佔用的是IPC的共享記憶體. 使用ipcs可以顯示共享記憶體的使用情況. 在Linux下, free命令中有個shared項, 在man手冊中說明是顯示共享記憶體的大小. 但實際上此項已經不在使用, 將一直是0. 觀察共享記憶體, 還是要透過ipcs . 我們可以透過ipcs -p, 顯示出cpid(建立此共享記憶體的程式ID)和lpid(最後使用此共享記憶體的程式ID). 在top中,也有一個共享記憶體列(SHARE),顯示程式佔用的共享記憶體。此處的“共享記憶體”,和IPC的共享記憶體,也就是Oracle中SGA所佔的記憶體仍不完全一樣。因此,觀察Oracle的“共享記憶體”,還是要用ipcs類命令。
       iostat也是一條常用的排故命令, 它的名字代有io字樣, 說明這條命令主要用於io方面的調節. 它顯示出的也有CPU方面的資訊, 不過更主要的還是I/O方面的資料. 檢視一下裝置的繁忙程度和讀/寫的速度, 如果在裝置很繁忙的情況下, 裝置的讀/寫速度低於正常水平, 這就有可能是裝置的問題. 如果不是裝置故障, 我們可以透過等待檢視進一步監測I/O方面的故障. 有關I/O的調優, 也是一個很大的專題, 我們在以後的系列文章中再一起討論. 
     sar命令有許多選項, 可以實現和上面命令類似的結果, 可以在排故或監控系統時使用. 具體可以參考man.
        總的來說, 對於"速度變慢"這類問題的解決, 最好是有正常時期的statspack報告, CPU的平均負載, I/O的平均速度, 頁交換的數量, 記憶體的使用資料等等資料. 有時候感覺到"速度變慢"並不一定是真的效能在降低, 而只是人的感覺. 對比正常時期的統計資料, 看差別是否巨大, 這樣可以更準確的判斷效能是否真的在降低. 而且, 透過對比統計資料, 往往可以更快的定位這類問題發生的原因. 
      希望這篇文章可以對資料庫的初學者有所幫助。同時,這篇文章寫的有點蒼促,有許多未盡之處,也希望大家多在此基礎上補充。

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

相關文章