mysql 資源占用過高分析和解決方法


分析和解決方案

1,情況描述:網站發標后,出現卡頓,最后出錯。

2,問題排查:最后一個版本的更新是在兩個星期前,照理來說,應該不是代碼的問題。但是一時找不到問題所在,還是先對代碼進行測試。使用排除法,修改數據后,在測試環境,生產環境測試,均正常。既然測試正常,那么排除代碼的問題。那懷疑可能是服務器的問題,接下來查看Linux環境的運行情況。

3,linux系統,命令top可以查看系統資源使用情況。最近兩次查看 ,如圖一,圖二。

       圖一

 圖二

由這兩個圖,可以看出來,mysql的服務幾乎把資源耗盡。

ps:發標前的兩三分鍾,CPU就已經高達140%,在60 - 140震盪。

top命令參數說明 

第一行的 load average 表示系統負載,即任務隊列的平均長度,3個數值分別統計最近1,5,15分鍾的系統平均負載 

  • 系統平均負載:單核CPU情況下,0.00 表示沒有任何負荷,1.00表示剛好滿負荷,超過1側表示超負荷,理想值是0.7;
  • 多核CPU負載:CPU核數 * 理想值0.7 = 理想負荷,例如:4核CPU負載不超過2.8何表示沒有出現高負載。

系統是2核,理想值是2 * 0.7 =1.4 。圖一的3.46,圖二的7.69,明顯大於理想值。

進程信息

  • K: %CPU = (CPU usage) 上次更新到現在的CPU時間占用百分比
  • 圖二的將近200%,兩核的最高是200%,因此系統CPU是滿負載運行。

因此在圖二的時候,系統卡頓了一段時間。如果再多些訪問量,系統應該就會出錯。

常見原因

系統執行應用提交查詢(包括數據修改操作)時需要大量的邏輯讀(邏輯 IO,執行查詢所需訪問的表的數據行數),所以系統需要消耗大量的 CPU 資源以維護從存儲系統讀取到內存中的數據一致性。

4,mysql分析數據運行狀態:show processlist;

在數據庫,執行上面語句,如圖

可以看出,這個查詢語句有問題。state為sending data。單獨拿出來在數據庫執行,時間有點久。當集中訪問時,數據庫占用資源飆升。

5,查看NGINX日志,訪問量並不多,訪問的比較多的鏈接和show processlist;查詢的情況基本吻合。

6,查看系統日志。圖二的時候,自動投標部分用了14秒。而測試的時候是2秒(測試時候,只是單獨發標)。真實發標時,訪問比較多,兩種情況的結合,影響變大了。單獨發標,或者單獨訪問多時,影響比較小。

7,解決方案

   1,優化數據庫語句

   2,增加資源,采用緩存,分布式等。這個方案保留。

    7.1,優化數據庫語句

    7.1.1 查看查找項目的查詢語句,投標表關聯的項目表的項目ID,即投標表的項目ID,pid加上索引(index)。

 圖:沒有索引時

圖:加上索引時

由上面兩個圖可以看出來,加上索引后,訪問的時間變為幾十毫秒。時間快了15- 20倍。

這樣訪問首頁和“我要投資”頁面的時候,系統資源壓力大大降低。

7.1.2 查詢公告

  首頁只要顯示5條數據,現在是查詢出了全部。在數據庫執行語句,查詢全部時,是100多ms,查詢限制5條時,是10多ms,時間快了10倍。

圖:content查詢修改前。

圖:content查詢修改后。

運行時間快了好幾倍。

7.1.3 查詢投資排行榜

   換種查詢方式,在數據庫里執行,由80ms到40ms,時間提高一倍。

SELECT sum(money)
        as investSum ,(select lname from P_user p1 where p1.id = userId ) as lname FROM personTransactionDetail where type = 4 and state in (1,3) GROUP BY userId,lname ORDER BY sum(money) DESC limit 5

改為:

SELECT sum(money)
        as investSum ,lname FROM personTransactionDetail a, P_user b where a.userId = b.id and type = 4 and state in (1,3) GROUP BY userId,lname ORDER BY sum(money) DESC limit 5

圖:投資排行榜修改前

圖:投資排行榜修改后

由200多ms到70ms,時間快了3倍。

連接查詢的效率比子查詢的高。

執行子查詢時,MYSQL需要創建臨時表,查詢完畢后再刪除這些臨時表,所以,子查詢的速度會受到一定的影響,這里多了一個創建和銷毀臨時表的過程。

因此,盡量用連接查詢。

參考:子查詢和關聯查詢 效率 ,表連接查詢與where后使用子查詢的性能分析 

結合自己的實驗,和別人的經歷,確實是連接查詢的效率比子查詢的高。

7.1.4 自動投標插入方面,先保留修改,看后面執行情況。

后續

修改后的運行情況:發標前,mysql服務,cpu的占用2%左右。發標中,不超過10%。自動投標部分,用時2m,正常了。

經過上述調整后,系統運行正常了。

對於訪問比較頻繁的首頁的每個連接做了數據庫查詢優化后,訪問數據都有所提升,因此效率大大提高了。

現在的網站主要的壓力都來自於數據庫,頻繁的數據庫訪問經常會使服務器死機。良好的數據庫設計和優化查詢語句是很重要的。

網站架構先是小型架構,逐漸演變成大型架構的。大型網站由小型網站演化而來,隨着業務發展,逐漸發展。參考:大型網站技術架構 ,個人GitHub筆記


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM