一、寫在前面:慢查詢的“冰山模型”
生產環境的性能問題像一座冰山,露出水面的只是“偶爾超時”的表象;隱藏在水下的,可能是索引缺失、數據傾斜、磁盤抖動、鎖競爭、內存抖動,甚至業務洪峰。慢查詢治理的第一步,是把整座冰山測繪出來,而非僅僅盯著冰尖。本文提出“三重定位”方法:
1. 慢日志:定位“哪條 SQL 慢”;
2. 審計表:定位“為什么慢”;
3. 火焰圖:定位“系統資源到底耗在哪”。
三者層層遞進,形成可復現、可量化、可落地的閉環。
二、第一重定位:慢日志——讓每一次超時都有跡可循
1. 采集策略
- 閾值設定:平均耗時超過 100 ms 或掃描行數超過 1 萬即落入慢日志。
- 采樣比例:高并發場景下采用 1/100 采樣,防止 I/O 放大。
- 持久化周期:按天轉儲,壓縮歸檔 30 天,支持回溯。
2. 字段解釋
- Query_time:端到端耗時,包含鎖等待、網絡往返。
- Rows_examined:掃描行數,用于判斷索引有效性。
- Lock_time:鎖等待時長,區分 CPU 與鎖瓶頸。
- Thread_id:可關聯審計表中的會話級指標。
3. 快速分類
通過正則或解析器,把慢日志按四類打標簽:
- 索引缺失型:Rows_examined 遠大于返回行數。
- 數據傾斜型:同一 SQL 不同參數耗時方差巨大。
- 鎖競爭型:Lock_time 占比高。
- 資源抖動型:Query_time 突刺,伴隨磁盤或 CPU 尖峰。
4. 可視化看板
把解析結果寫入時序數據庫,按小時聚合:
- 慢查詢總量趨勢圖
- 平均耗時熱力圖
- Top 20 SQL 排行榜
三、第二重定位:審計表——把模糊感覺變成量化指標
1. 審計表結構
在業務庫旁路部署一張會話級審計表,字段包括:
- sql_digest:SQL 指紋,去掉常量、統一大小寫。
- exec_count:執行次數。
- sum_latency:總耗時。
- sum_rows_sent:返回行數總和。
- plan_hash:執行計劃指紋,用于捕捉計劃突變。
2. 采樣策略
- 會話級采樣:每 1000 次執行采樣一次,避免高并發下的寫入風暴。
- 計劃突變采樣:當 plan_hash 變化時強制記錄。
3. 關聯分析
把審計表與慢日志按 sql_digest 關聯,可得出:
- 某條 SQL 在慢日志中出現 1 次,在審計表出現 10 萬次 → 命中率低但影響面大。
- 同一指紋出現多個 plan_hash → 計劃抖動導致偶發慢。
4. 自動基線
利用 30 天審計數據,計算每條 SQL 的平均耗時 μ 與標準差 σ,自動生成基線閾值 μ+3σ。觸發閾值即產生告警,而非人工拍腦袋。
四、第三重定位:火焰圖——在 CPU 的森林里尋找熱點
1. 采集方式
- 用戶態:對數據庫進程進行 perf record,抓取 CPU 調用棧。
- 內核態:systemtap 或 eBPF,觀測 I/O、調度、內存拷貝。
2. 火焰圖閱讀法
- 寬柱即熱點:解析器、執行器、InnoDB 層、B+ 樹查找、鎖等待。
- 顏色無意義,高度代表調用深度,寬度代表 CPU 時間占比。
3. 與慢日志的交叉驗證
- 慢日志顯示“某 SQL 平均 300 ms”;
- 火焰圖顯示“B+ 樹查找占 70%”;
- 二者結合即可斷定:索引缺失導致全表/全索引掃描。
4. 周期對比
在慢查詢高峰時段與低峰時段各采一張火焰圖,做差分火焰圖,可快速定位“新增熱點”。
五、三重定位的協同流程:采集、清洗、關聯、歸因
1. 采集
慢日志 → 本地文件;審計表 → 業務庫;火焰圖 → 性能分析節點。
2. 清洗
統一時間戳、脫敏、壓縮、去重。
3. 關聯
以 sql_digest + 時間窗口為鍵,把三類數據 join 到同一條記錄。
4. 歸因
輸出“根因標簽”:索引缺失、數據傾斜、鎖競爭、資源抖動、執行計劃突變。
六、典型場景剖析:四類慢查詢的完整治理案例
場景 A:索引缺失型
- 慢日志:Rows_examined 100 萬,返回 10 行。
- 審計表:該 SQL 占全天總延遲 30%。
- 火焰圖:B+ 樹查找占 80%。
治理:添加復合索引,平均耗時從 300 ms 降至 3 ms。
場景 B:數據傾斜型
- 慢日志:同一指紋耗時 50 ms~5 s 波動。
- 審計表:參數分布極不均勻。
- 火焰圖:CPU 使用平穩。
治理:把傾斜值單獨分區,或改寫 SQL 用覆蓋索引。
場景 C:鎖競爭型
- 慢日志:Lock_time 90%,Query_time 100 ms。
- 火焰圖:mutex 等待占 60%。
治理:拆大事務、降低隔離級別、批量提交。
場景 D:執行計劃突變
- 慢日志:某 SQL 突然全表掃描。
- 審計表:plan_hash 變化。
- 火焰圖:全表掃描函數出現。
治理:強制指定索引或更新統計信息。
七、指標與基線:如何定義“真的慢”
1. 業務層 SLA
P99 < 100 ms,P95 < 50 ms。
2. 技術層基線
- CPU:單核利用率 < 70% 為健康。
- I/O:磁盤 util < 60%。
- 鎖:InnoDB row lock wait < 10 ms。
3. 動態基線
利用滑動窗口算法,每周自動更新閾值,避免“刻舟求劍”。
八、治理閉環:從告警到復盤
1. 告警
慢日志 + 審計表雙閾值觸發,減少誤報。
2. 工單
自動生成 JIRA 工單,字段包括:SQL 指紋、根因標簽、影響面、建議方案。
3. 修復
DBA、開發、運維三方評審,灰度上線。
4. 復盤
7 天后回顧修復效果,更新知識庫,沉淀到“慢查詢百科”。
九、常見誤區與最佳實踐
誤區 1:只盯著慢日志,不關聯審計表 → 漏掉高頻次、低延遲抖動。
誤區 2:火焰圖采樣頻率過低 → 錯過短時尖峰。
誤區 3:一次性加很多索引 → 寫放大,適得其反。
最佳實踐:
- 任何索引上線前先跑 24 小時影子測試;
- 每周跑一次全庫統計信息更新;
- 火焰圖采樣周期 ≤ 10 ms,持續 30 秒即可。
十、工具鏈地圖:從操作系統到數據庫引擎
- 慢日志解析:pt-query-digest、內置解析器
- 審計插件:官方 Audit Plugin、社區版
- 火焰圖:perf、systemtap、eBPF、FlameGraph 腳本
- 可視化:Grafana、時序數據庫
- 告警:Alertmanager、短信、IM 機器人
十一、未來展望:自適應診斷與 AI 加持
1. 根因模型
用機器學習對歷史慢日志打標簽,訓練出“根因分類器”,新慢查詢 5 秒內給出預測。
2. 自愈系統
索引缺失 → 自動生成候選索引 → 影子驗證 → 灰度上線。
3. 智能容量預測
基于審計表增長率,預測未來 30 天的慢查詢風險,提前擴容或優化。
十二、結語:讓慢查詢從“火警”變成“天氣預報”
慢查詢治理從來不是一次性的“救火”,而是持續性的“氣候觀測”。慢日志告訴我們“哪里下雨了”,審計表告訴我們“雨有多大”,火焰圖告訴我們“為什么下雨”。把這三重定位變成日常流程,就能把不可預測的“火警”變成可提前準備的“天氣預報”,讓數據庫性能真正步入可控、可演進、可持續的軌道。