工作過程中有時候會接收到資料庫伺服器器load 飙高的報警,比如:
load1 15.25 base: 8.52,collect time:2014-08-30
如何處理load 異常飙高的報警呢? 本文嘗試從原理,原因,解決方法來闡述這類問題的解決思路。
一 原理分析
cpu作為伺服器的關鍵資源經常成為性能瓶頸的根源,cpu使用率高并不總是意味着cpu工作繁忙,它有可能是正在等待其他子系統。在進行性能分析時,将所有子系統當做一個整體來看是非常重要的,因為在子系統中可能會出現瀑布效應。衡量cpu 系統負載的名額是load,load 就是對計算機系統能夠承擔的多少負載的度量,簡單的說是程序隊列的長度。簡單的例子比如食堂有五個視窗,當有小于五個學生來打飯,五個視窗都能及時處理,但是當學生個數超過5個,必然會出現等待的學生。請求大于目前的處理能力,會出現等待,引起load升高。
load average 就是一段時間(1min,5min,15min)内平均load。平均負載的最佳值是1,這意味着每個程序都可以在一個完整的cpu 周期内完成。
14:50:31 up 166 days, 1:54, 295 users, load average: 0.05, 0.04, 0.00
二 原因分析
一般導緻mysql伺服器load飙高的原因可能有以下幾種情況:
1 業務并發調用全表掃描/帶有order by 排序的sql語句.
2 sql語句沒有合适索引/執行計劃出錯/update/delete where掃描全表,阻塞其他通路相同表的sql執行.
3 存在秒殺類似的業務比如聚劃算10點開團或者雙十一秒殺,瞬時海量通路給資料庫帶來沖擊。
4 資料庫做邏輯備份(需要全表掃描)或者多執行個體的壓縮備份(壓縮時需要大量的cpu計算,會導緻系統伺服器load飙高)
5 磁盤寫入方式改變 比如有writeback 變為 write through
raid卡都有寫cache(battery backed write cache),寫cache對io性能的提升非常明顯,因為掉電會丢失資料,是以必須由電池提供支援。
電池會定期充放電,一般為90天左右,當發現電量低于某個閥值時,會将寫cache政策從writeback置為writethrough,相當于寫cache會失效,這時如果系統有大量的io操作,可能會明顯感覺到io響 應速度變慢,cpu 隊列堆積系統load 飙高。
6 其他 歡迎補充 。
三 解決方法
在load average 高的情況下如何鑒别系統瓶頸?如何判斷系統是否已經over load呢?要去檢查判斷是cpu不足,還是io不夠快造成或是記憶體不足?
這裡筆者處理的方式 一般根據cpu數量去判斷,也就是load平均要小于cpu的數量,負載的正常值在不同的系統中有着很大的差别。在單核處理器的工作站中,1或2都是可以接受的。多核處理器的伺服器(比如24核)上,load 會到達20 ,甚至更高。以多執行個體混合公用一台24核實體機為例,當dba收到資料庫伺服器load 飙高報警後,一般的處理步驟
a) 資料庫層面
1 top -u mysql -c 檢查目前占用cpu資源最多的程序指令。-c 是為了顯示出程序對應的執行指令語句,友善檢視是什麼操作導緻系統load飙高。
2 根據不同的情況擷取pid 或者mysql的端口号
3 如果是mysql 資料庫服務導緻laod 飙高,則可以使用如下指令
show processlist;
select * from information_schema.processlist where command <> 'sleep' and time>100;
或
orzdba 工具檢查邏輯讀/thread active的值。用法orzdba --help
orztop 工具檢查目前正在執行的慢sql,用法orztop -p $port
4 擷取異常的sql之後,剩下的比較好解決了。結合第一部分中的幾條原因
a 選擇合适的索引
b 調整sql 語句 比如對應order by 分頁采用延遲關聯
c 業務層面增加緩存,減少對資料庫的直接通路等
b) os 系統層面 檢查系統io
使用iostat 指令檢視r/s(讀請求),w/s(寫請求),avgrq-sz(平均請求大小),await(io等待), svctm(io響應時間)
r/s ,w/s是每秒讀/寫請求的次數。
util是裝置的使用率。如果它接近100%,通常說明裝置能力趨于飽和(并不絕對,比如裝置有寫緩存)。有時候可能會出現大于100%的情況,這多半是計算時四舍五入引起的。
svctm是平均每次請求的服務時間。這裡有一個公式:(r/s+w/s)*(svctm/1000)=util。舉例子:如果util達到100%,那麼此時 svctm=1000/(r/s+w/s),假設iops是1000,則svctm大概在1毫秒左右,如果長時間大于這個數值,說明系統出了問題。
await是平均每次請求的等待時間。這個時間包括了隊列時間和服務時間,也就是說,一般情況下,await大于svctm,它們的內插補點越小,隊列時間越短,反之內插補點越大,隊列時間越長,說明系統出了問題。
avgqu-sz是平均請求隊列的長度。毫無疑問,隊列長度越短越好。