在一個風和日麗的下午,奮哥哥突然接到業務方線上業務資料庫CPU資源告警資訊,立馬放下手裡的枸杞登入業務方阿裡雲控制台檢視具體問題。
對于資料庫目前正在發生中的問題,我們首先從資料庫實時會話資訊中嘗試抓取有效資訊,可以看到該告警執行個體的會話已經出現堆積狀态,大量會話處于"Sending data"狀态且從TIME字段可以看到這些會話長時間執行未結束。會話長時間執行表示目前會話一直占用的資料庫資源未釋放,且堆積會話基本為同一類型的業務SQL,這也就是導緻我們資料庫資源打高的問題SQL。

我們拎出這個問題SQL登入資料庫檢視SQL的執行計劃,對問題SQL進行分析,從SQL執行計劃中我們很明顯發現一個資源消耗比較大的操作"ALL"全表掃描操作,而且比較詭異的一點是,a表進行表關聯possible_keys明明是primary但是卻沒有使用,是以我們下一步的方向就是排查為什麼表關聯沒有有效利用索引。
導緻索引失效的問題的原因最常見的就是隐式轉換,關于隐式轉換我們之前的文章也做過比較詳細的講解,總體概括主要是以下幾個場景:
1)傳遞資料類型和字段類型不一緻
2)關聯字段類型不一緻
3)關聯字段字元集不一緻
4)校驗規則不一緻
在表關聯字段索引失效的情況下,可能導緻索引失效的場景主要是2~4,于是我們馬上檢視表關聯字段相關資訊進行一一驗證。emmmm,查詢到的結果卻似乎有些不盡人意,表關聯字段均是bigint類型,完美的規避掉了以上所有可能。
再次陷入沉思,在沒有發生隐式轉換的情況下索引一般都是會有效利用的,除非MySQL優化器認為ALL全表掃描的效率并不差。我們知道,MySQL優化器會通過具體表的統計資訊基于CBO進行代價計算,幫我們選擇最佳執行計劃。但是統計資訊并不是完全精确的,某些時候可能會出現一定的誤差,也正是因為統計資訊的誤差,就可能導緻MySQL優化器錯誤的選擇一個并不是很好的"最佳執行計劃"。接下來我們就可以進一步檢視表的統計資訊以及hint進行驗證。
表關聯對應的統計資訊
通過hint強制走primary索引觀察執行計劃、并測試執行效率
問題排查到這裡,導緻該SQL大量消耗CPU資源的原因也就水落石出了。對于業務方目前的CPU打高的情況,我們可以建議業務方先将目前堆積的會話進行Kill,避免影響其他正常的業務查詢,等資料庫CPU資源有所回落後,在資料庫執行"analyze table"對問題表的統計資訊重新采集,統計資訊更新後MySQL優化器就可以正确的選擇最佳執行計劃。
統計資訊更新:
執行計劃更新:
雖然客戶的問題已經處理,對于本案例還是有一些點值得我們思考:
索引失效的場景都有哪些?
隐式轉換
統計資訊不準确
MySQL統計資訊是如何更新采集?
在MySQL中有一些參數設定決定了統計資訊采集的行為方式,一般情況下不會做特别設定,我們需要正确的了解這些參數,明白統計資訊隻是一個統計估計值,并不是絕對精準。
統計資訊相關參數
innodb_stats_method 預設nulls_equal,表示統計資訊時把所有的null當作等值對待
innodb_stats_auto_recalc 是否打開自動化采集統計資料 ,預設打開,當表資料量更新10%觸發重新采集統計資訊
innodb_stats_on_metadata 預設關閉,若該參數開啟時表示資料庫執行"show table status",通路"INFORMATION_SCHEMA.TABLES or
INFORMATION_SCHEMA.STATISTICS"時,都會觸發重新采集統計資訊的操作
innodb_stats_persistent 統計資訊是否持久化到磁盤,預設打開。持久化磁盤當資料庫重新啟動後可從磁盤讀取。
innodb_stats_persistent_sample_pages 預設20,對于持久化存儲統計資訊的表,每次重新采集資訊需要采集20個索引頁進行分析
innodb_stats_transient_sample_pages 預設8,對于非持久化的表,其統計資訊重新采集需要掃描8個索引頁進行分析
MySQL幾種重新采集統計資訊的時機
新打開一張表時
表資料變更超過10%觸發該表的統計資訊重新采集
當innodb_stats_on_metadata參數打開,資料庫執行"show table status",通路"INFORMATION_SCHEMA.TABLES or INFORMATION_SCHEMA.STATISTICS"時
手動執行analyze tables時
關于analyze table操作
執行該操作需要具有該表的select/insert權限
支援Innodb、Myisam、NDB存儲引擎下的表,不支援視圖
支援對分區表中某個分區單獨執行統計分析:alter table ... analyze partition在執行analyze期間,會對該表加一個讀鎖。
探尋完技術的真理,奮哥哥又默默的拿起了曾經放下的枸杞。