MySQL Insert語句單個批次數量過多導致的CPU效能問題分析
【問題】
最近有臺伺服器比較頻繁的CPU報警,表現的特徵有CPU sys佔比偏高,大量慢查詢,大量併發執行緒堆積。後面開發對insert的相關業務限流後,伺服器效能恢復正常。
【異常期間執行緒處理情況】
下圖是當時生產環境異常時抓取的資訊,該事務正在執行insert,已經執行5秒,執行緒執行在innodb核心,狀態是thread declared inside InnoDB,還有4906 tickets可用
統計了下有64個執行緒在innodb層,同時看到還有280個執行緒在排隊等待進入innodb執行緒,狀態是sleeping before entering InnoDB
innodb層的併發執行緒執行的SQL比較慢,產生了阻塞,導致了mysql的併發執行緒堆積。
【哪些SQL執行慢】
從正在執行的SQL中,看到了insert的慢查詢SQL語句,統計了下這句SQL批量插入大於342條記錄(SQL被截斷)
【批量insert的效能測試】
類似這種批量的insert SQL會對MySQL效能造成影響嗎,多大的批次比較合理呢,做了下面測試
在測試伺服器上新建測試表(表結構同生產環境),並定義了5個插入指令碼,分別為單條insert,每10條1個批次insert,每50條1個批次insert,每100條1個批次insert,每340條1個批次insert
用壓測工具模擬512個併發執行緒的情況下,不同型別的SQL插入100W條記錄伺服器的效能情況,下表是壓測統計
資料量 |
併發執行緒 |
執行時間(秒) |
每秒insert |
慢查詢數量 |
Context switch |
CPU使用率 |
CPU sys佔比 |
|
普通insert(1條) |
1000000 |
512 |
33 |
3W |
0 |
79W |
73% |
39% |
批量SQL(10條) |
1000000 |
512 |
23 |
4.3W |
0 |
49W |
78% |
56% |
批量SQL(50條) |
1000000 |
512 |
21 |
4.7W |
0 |
42W |
80% |
60% |
批量SQL(100條) |
1000000 |
512 |
15 |
6.6W |
20 |
53W |
70% |
45% |
批量SQL(340條) |
1000000 |
512 |
15 |
6.6W |
200 |
38W |
86% |
70% |
下圖是批量SQL(340條)執行時的效能情況,可以看到當每100條記錄一個批次執行insert時,開始出現慢查詢,每340條1個批次執行insert時,在高併發的情況下,會產生大量的慢查詢,這個現象接近於我們目前生產環境異常時的情況
【優化方案】
對於MySQL需要插入大量資料時,每次單條的insert效能較差,為了提升insert效能,我們採用了每批次多條記錄同時insert的方法。
但當批次增大到一定數量時,在高併發訪問的情況下,單個批次執行的效能會出現較大的下降,出現大量慢查詢,併發執行緒堆積,CPU上升出現瓶頸, innodb層的併發執行緒處理被慢查詢阻塞,後面只能通過限流來緩解效能問題。
根據上面的測試結論, 建議控制熱表單個批次insert的記錄條數,最好單個批次控制在10條左右 (因為即使調大到50條,插入效能沒有大的提升,在高併發場景下,首先要保證當前SQL的執行效能)。
【優化後CPU告警消失,執行平穩】
Linux公社的RSS地址 : ofollow,noindex" target="_blank">https://www.linuxidc.com/rssFeed.aspx
本文永久更新連結地址: https://www.linuxidc.com/Linux/2018-10/154981.htm