1. 程式人生 > >MySQL Insert語句單個批次數量過多導致的CPU性能問題分析

MySQL Insert語句單個批次數量過多導致的CPU性能問題分析

padding 異常 線程處理 mys add context table 占比 我們

原文: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告警消失,運行平穩】

技術分享圖片

技術分享圖片

MySQL Insert語句單個批次數量過多導致的CPU性能問題分析