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顯示段中,會出現明顯的資料扭曲。此類問題可以將innodb_adaptive_hash_index參數關閉,也就是直接棄用AHI特性,已有資料表明在混合讀寫的情境下AHI也有可能帶來負面的效能影響,關閉後對整體業務的影響不是很大。
系統BUG
系統BUG是相對少見的問題,例如早期出現的進程死結以及因表上統計資訊置為0而導致的全表掃描等。隨著產品的快速迭代,因系統BUG引發的CPU問題相對較少。然而,在排查此類問題時,涉及很多的核心層面資訊,您自行處理可能有一定的難度。建議聯絡我們以擷取支援人員進行問題排查。