CPU作為資料庫的核心資源,是日常營運中重點關注的對象。CPU的過度使用將導致應用回應時間(RT)的增加、業務的卡頓,甚至更嚴重的情況可能導致資料庫執行個體掛起(hang死)、發生高可用(HA)問題,從而嚴重影響現網任務。因此,正常情況下,CPU的監控應設定安全水位,一旦超出安全水位應及時進行處理,以避免引發不可預期的嚴重後果。
現網業務中的CPU使用率
隨著業務的增長,資料庫叢集的規格可能已經不能滿足業務流量的上漲需求。此時由於流量的不斷增長,資料庫叢集的使用率逐漸提升,CPU使用率也逐漸升高。如果從效能曲線進行觀察,必然存在某個指標(如QPS/IOPS)呈上漲趨勢,與CPU使用率上漲趨勢相似。
非預期內CPU使用率增長
導致CPU使用率非預期增長的情況比較複雜,本文主要針對比較常見的幾個現象進行說明,包括慢查詢、活躍線程高、核心配置不合理以及系統BUG。
慢查詢
正常情況下,CPU使用率的增長,一般是由於SQL語句不合理,產生了慢查詢,同時活躍線程堆積導致CPU使用率過高。但是一定要區分清楚,是由於慢查詢導致的CPU使用率高,還是由於其他資源滿載導致查詢變慢導致的CPU使用率高。
您可以在PolarDB控制台的菜單中,查看慢查詢情況。如果慢查詢中有資料,就需要對這些資料進行分析。如果在慢日志明细頁簽中,掃描行遠遠大於返回行數,則說明是慢查詢導致的CPU使用率過高。
此處主要針對TP類查詢進行分析,需要排除掉count類查詢,一些AP類查詢的掃描行數確實很大。
TP類查詢業務的讀寫資料量都非常小,如果某個查詢的掃描資料量非常大,那麼大機率是由於索引缺失導致。例如下述查詢語句在慢查詢列表中顯示掃描資料量為1萬+,但返回資料為1條,那麼很明顯在name列上有索引缺失的情況。
SELECT * FROM table1 WHERE name='testname';那麼可以通過下述語句確認在name列上是否有索引。
SHOW index FROM table1;如果
name列上沒有索引,可以通過下述語句添加索引列,消除此類巨量資料量掃描導致的慢查詢。ALTER TABLE table1 ADD KEY ix_name (name);如果
name列上有索引,可以通過下述語句查看SQL語句的執行計畫,確認是否使用了正確的索引。EXPLAIN SELECT * FROM table1 WHERE name='testname';如果發現
name列有索引,但沒有被使用,有可能是出現了統計資訊不準確導致產生了錯誤的執行計畫。可以通過下述語句重建表上的統計資訊用以糾正錯誤計劃。ANALYZE TABLE table1;執行完成後,再通過下述語句確認是否使用了正確的索引。
EXPLAIN SELECT * FROM table1 WHERE name='testname';
活躍線程高
活躍線程高一定會帶來CPU使用率的增長。抽象來說,MySQL實現中,每一個CPU只能在同一時間內處理一個請求。假設是16C規格的叢集,最多隻能同時處理16個請求。但是要注意,這裡的請求指的是核心層面,而非應用的並發層面。您可以在PolarDB控制台的菜單中,查看會話情況。
如果排除掉慢查詢導致的請求無法正常處理,活躍線程堆積一般都是由於現網業務流量增長造成的。通過查看效能曲線,如果整體流量以及請求趨勢和活躍線程的堆積趨勢一致,那麼說明叢集資源已經達到上限,此時需要通過對資料庫叢集增加唯讀節點或者擴容叢集規格來解決。
需要注意的是,在活躍線程達到臨界點時,可能在CPU層面開始產生爭搶,核心中會產生大量的mutex獨佔鎖定,此時效能曲線表現特徵為高CPU使用率、高活躍線程、低IO或低QPS。另外一種情況是突然的業務洪峰,建立連線速度非常快,也可能在CPU層面產生大量爭搶,從而導致請求堆積。此類問題一般可以通過開啟叢集的Thread Pool特性進行流控緩解。如果活躍線程有所緩解,同時還要注意應用側是否已經產生了業務堆積,如果CPU負載較高同時活躍線程依然高居不下,此時則同樣要考慮是不是對叢集進行擴容操作。
另有一種情況是前端串連風暴導致叢集流量瞬間堆積,此時流量屬於異常流量,一般出現在流量資料被爬蟲拉取資料的情境下。此時可以通過SQL限流的方式進行請求拒絕,具體操作請參見會話管理。
核心配置不合理
自建MySQL的參數是通用情境下的標準配置,對於個別業務可能不太適用,需要進行微調。有些問題在業務上線初期資料量較少的情況下不會觸發,但是隨著時間的推移,業務資料量增大,在特定條件下有些問題就會暴露出來。
比較常見的問題會出現記憶體使用量爭搶。在MySQL體系中,記憶體主要作為資料緩衝使用,這意味著資料需要不斷地迭代,最常用是buffer pool和innodb_adaptive_hash_index記憶體地區。整個資料庫系統的快取區域,是資料交換最為頻繁的位置,如果記憶體不足和記憶體頁爭搶,則會出現各種異常的堆積和慢查詢。最典型的表現是資料庫突然CPU上漲打滿,並且出現慢查詢。經過排查後發現該問題並非索引缺失,這個時候就有可能是記憶體系統發生了問題。
例如:在進行truncate table操作時,MySQL要遍曆buffer pool將truncate表的資料頁全部驅逐。此時大規格的叢集中,如果innodb_buffer_pool_instances配置為1並且並發相對較高的情況下,就有可能出現爭搶問題。這個問題在業務上線初期就可以發現,一般來說可以將innodb_buffer_pool_instances的取值與CPU核心數對齊,將buffer pool進行分桶,就可以規避此類問題。
另外一種情境是innodb_adaptive_hash_index出現爭搶,比較明顯的表現是執行下述命令時會出現大量的hash0hash.cc等待。
SHOW ENGINE innodb STATUS;在AHI顯示段中,會出現明顯的資料扭曲。
insert 0, delete mark 0, delete 0
Hash table size 25499819, node heap has 20720 buffer(s)
Hash table size 25499819, node heap has 25111 buffer(s)
Hash table size 25499819, node heap has 23884 buffer(s)
Hash table size 25499819, node heap has 16835 buffer(s)
Hash table size 25499819, node heap has 23132 buffer(s)
Hash table size 25499819, node heap has 189284 buffer(s)
Hash table size 25499819, node heap has 38864 buffer(s)
Hash table size 25499819, node heap has 49094 buffer(s)
5469.32 hash searches/s, 5282.36 non-hash searches/s此類問題可以將innodb_adaptive_hash_index參數關閉,也就是直接棄用AHI特性,已有資料表明在混合讀寫的情境下AHI也有可能帶來負面的效能影響,關閉後對整體業務的影響不是很大。
系統BUG
系統BUG是相對少見的問題,例如早期出現的進程死結以及因表上統計資訊置為0而導致的全表掃描等。隨著產品的快速迭代,因系統BUG引發的CPU問題相對較少。然而,在排查此類問題時,涉及很多的核心層面資訊,您自行處理可能有一定的難度。建議聯絡我們以擷取支援人員進行問題排查。