Linux服務器上MySQL CPU使用率過高問題排查與定位

文章目錄

    • 一、CPU高負載常見成因分析
      • 1.1 全表掃描與索引缺失
      • 1.2 復雜計算與臨時表
      • 1.3 鎖競爭與線程上下文切換
      • 1.4 查詢優化器誤判
      • 1.5 硬件資源瓶頸
    • 二、操作系統級初步定位
      • 2.1 使用top定位MySQL進程
      • 2.2 用pidstat分析線程級CPU
      • 2.3 vmstat分析系統負載
    • 三、數據庫層深度診斷
      • 3.1 SHOW PROCESSLIST鎖定問題SQL
      • 3.2 EXPLAIN分析執行計劃
      • 3.3 SHOW PROFILE分析階段耗時
    • 四、實戰案例:訂單查詢模塊CPU飆升排查
      • 4.1 問題現象
      • 4.2 操作系統層排查
      • 4.3 數據庫層診斷
      • 4.4 優化方案與驗證
    • 五、預防措施與日常監控
      • 5.1 建立索引優化機制
      • 5.2 開啟慢查詢日志
      • 5.3 自動化監控腳本
    • 總結

在Linux服務器環境中,MySQL數據庫出現CPU使用率過高是常見的性能故障。本文將結合實際排查流程,通過具體工具和案例,詳細講解如何定位與分析MySQL CPU高負載問題。內容涵蓋常見成因分析、操作系統級監控、數據庫層診斷及實戰優化案例,全程以實操為導向,避免理論堆砌。

一、CPU高負載常見成因分析

1.1 全表掃描與索引缺失

當查詢語句未命中索引時,MySQL會觸發全表掃描(type: ALL),導致大量CPU消耗在磁盤數據讀取與過濾上。典型場景包括:

  • WHERE條件字段未建立索引
  • 索引因字段類型不匹配、函數運算等原因失效

案例:某電商訂單表查詢語句SELECT * FROM orders WHERE create_time > '2023-01-01'未在create_time字段建索引,執行時掃描1000萬條記錄,CPU使用率飆升至80%。

1.2 復雜計算與臨時表

包含大量計算函數(如COUNT(DISTINCT)GROUP_CONCAT)或隱式創建臨時表的查詢(如EXPLAIN結果中Extra包含Using temporary),會消耗大量CPU進行數據處理。例如:

-- 含DISTINCT和分組的復雜查詢
SELECT user_id, COUNT(DISTINCT product_id) AS cnt 
FROM order_items 
GROUP BY user_id 
HAVING cnt > 10;

1.3 鎖競爭與線程上下文切換

InnoDB行鎖競爭或表鎖沖突會導致線程頻繁等待鎖釋放,伴隨大量上下文切換(Context Switch)。通過vmstat工具查看cs(上下文切換次數)值,若遠超正常水平(如每秒>10萬次),需排查鎖問題:

# 每2秒采樣一次,共5次
vmstat 2 5

1.4 查詢優化器誤判

MySQL優化器可能因統計信息過時(如未執行ANALYZE TABLE),選擇非最優執行計劃。例如誤判掃描行數,導致放棄索引改用全表掃描:

-- 執行計劃顯示掃描100行,實際掃描10萬行
EXPLAIN SELECT * FROM users WHERE status = 'active';

1.5 硬件資源瓶頸

當CPU核心數不足或內存帶寬受限,即使查詢優化良好,也可能出現CPU瓶頸。需通過nproc查看CPU核心數,free -h檢查內存使用情況:

# 查看邏輯CPU核心數
nproc --all

二、操作系統級初步定位

2.1 使用top定位MySQL進程

通過top命令實時監控系統進程,按shift + p以CPU使用率排序,確認mysqld進程是否為CPU高占用源頭:

top -c  # -c參數顯示完整命令行

關鍵信息

  • %CPU:進程占用CPU百分比(多核CPU需按核心數折算,如8核CPU中某進程%CPU達160%表示占用2個核心)
  • COMMAND:顯示當前執行的SQL片段(若開啟show_compatibility_56參數)

案例:發現mysqld進程%CPU持續在150%(8核系統),命令行顯示SELECT * FROM logs WHERE user_id = 123,初步判斷為該查詢引發。

2.2 用pidstat分析線程級CPU

pidstat可按線程維度統計CPU使用情況,定位具體線程ID(TID):

# 監控mysqld進程(PID=12345)的線程,每2秒采樣一次
pidstat -t -p 12345 2

輸出解讀

Linux 5.4.0-105-generic (server01)   2024-12-10 14:30:00   _x86_64_    (8 CPU)14:30:00  UID       PID   TID    %usr %system  %guest   %wait    %CPU   CPU  Command
14:30:02    1001    12345 12346  15.00   5.00    0.00    0.00   20.00     1  mysqld
14:30:02    1001    12345 12347  18.00   7.00    0.00    0.00   25.00     3  mysqld
  • TID:線程ID(需轉換為16進制,用于后續SHOW PROCESSLIST匹配)
  • %CPU:該線程占用CPU百分比

2.3 vmstat分析系統負載

通過vmstat查看系統整體負載與CPU狀態:

vmstat -n 2 5  # 每秒采樣,共5次

關鍵指標

  • r(運行隊列長度):等待CPU資源的進程數,若持續大于CPU核心數2倍以上,表明CPU瓶頸
  • us(用戶態CPU):應用程序消耗CPU占比
  • sy(系統態CPU):內核操作消耗CPU占比
  • cs(上下文切換):每秒上下文切換次數

案例:發現r=6(8核CPU),us=70%sy=25%cs=80000/s,判斷為用戶態應用導致CPU高負載,伴隨大量上下文切換。

三、數據庫層深度診斷

3.1 SHOW PROCESSLIST鎖定問題SQL

通過SHOW PROCESSLIST查看當前活躍線程,重點關注:

  • State:線程狀態(如Sending dataCopying to temporary table
  • Time:持續執行時間(秒)
  • Info:具體SQL語句
SHOW PROCESSLIST;

輸出示例

+-----+------+-----------+------+---------+------+-------+----------------------------------------+
| Id  | User | Host      | db   | Command | Time | State | Info                                   |
+-----+------+-----------+------+---------+------+-------+----------------------------------------+
| 123 | root | localhost | test | Query   | 120  | Sending data | SELECT * FROM large_table WHERE id < 100000 |
| 124 | root | localhost | test | Sleep   | 3600 |       | NULL                                   |
+-----+------+-----------+------+---------+------+-------+----------------------------------------+
  • Time較長(如>60秒)的線程,可通過KILL [Id]終止
  • 記錄Id對應的TID(需通過SELECT CONNECTION_ID();獲取當前線程ID與操作系統TID的映射關系)

3.2 EXPLAIN分析執行計劃

SHOW PROCESSLIST中定位的慢查詢,使用EXPLAIN分析執行計劃,重點檢查:

  • type:是否為低效的ALL(全表掃描)或index(索引全掃描)
  • key:是否使用預期索引
  • rows:預估掃描行數是否與實際數據量匹配
  • Extra:是否包含Using temporaryUsing filesort等性能損耗標記

案例:慢查詢SELECT * FROM orders WHERE status = 'paid' AND create_time > '2024-01-01'的執行計劃:

EXPLAIN SELECT * FROM orders 
WHERE status = 'paid' AND create_time > '2024-01-01';
+----+-------------+--------+------------+------+---------------+------+---------+------+--------+----------+----------------------------------------------+
| id | select_type | table  | partitions | type | possible_keys | key  | key_len | ref  | rows   | filtered | Extra                                        |
+----+-------------+--------+------------+------+---------------+------+---------+------+--------+----------+----------------------------------------------+
|  1 | SIMPLE      | orders | NULL       | ALL  | idx_status    | NULL | NULL    | NULL | 100000 |    10.00 | Using where; Using temporary; Using filesort |
+----+-------------+--------+------------+------+---------------+------+---------+------+--------+----------+----------------------------------------------+

問題定位

  • type=ALL:全表掃描
  • Extra包含Using temporaryUsing filesort:觸發臨時表和文件排序
  • 未使用statuscreate_time索引

3.3 SHOW PROFILE分析階段耗時

通過SHOW PROFILE獲取SQL執行各階段耗時,定位瓶頸環節:

-- 開啟profiling
SET profiling = 1;-- 執行目標SQL
SELECT * FROM orders WHERE ... ;-- 獲取最近一次查詢的profile
SHOW PROFILE FOR QUERY (SELECT query_id FROM information_schema.PROFILING ORDER BY query_id DESC LIMIT 1);

典型輸出

+----------------------+----------+------------+-------------+
| Status               | Duration | CPU_user   | CPU_system  |
+----------------------+----------+------------+-------------+
| starting             | 0.00003  | 0.00001    | 0.00001     |
| checking permissions | 0.00001  | 0.00000    | 0.00000     |
| Opening tables       | 0.00002  | 0.00001    | 0.00001     |
| System lock          | 0.00001  | 0.00000    | 0.00000     |
| optimizing           | 0.00005  | 0.00003    | 0.00002     |
| statistics           | 0.00012  | 0.00008    | 0.00004     |
| preparing            | 0.00004  | 0.00002    | 0.00002     |
| executing            | 0.00003  | 0.00001    | 0.00001     |
| Sending data         | 2.56789  | 1.89023    | 0.67766     |
| end                  | 0.00002  | 0.00001    | 0.00001     |
+----------------------+----------+------------+-------------+
  • Sending data階段耗時占比超70%,通常為結果集過大或網絡傳輸瓶頸
  • optimizing階段耗時高,可能為查詢優化器計算復雜,需更新統計信息或重構查詢

四、實戰案例:訂單查詢模塊CPU飆升排查

4.1 問題現象

某電商平臺訂單查詢頁面響應緩慢,監控顯示Linux服務器MySQL進程CPU使用率持續達180%(8核系統),topmysqld進程%CPU為180%,COMMAND顯示正在執行訂單列表查詢。

4.2 操作系統層排查

  1. top確認進程

    top -c | grep mysqld
    # 輸出顯示PID=23456,%CPU=180%,命令行包含"SELECT o.*, u.name FROM orders o JOIN users u ON o.user_id=u.id WHERE o.status='paid'"
    
  2. pidstat線程分析

    pidstat -t -p 23456 2
    # 發現TID=23458(16進制為0x5BCA)和TID=23459(0x5BCB)兩個線程各占90% CPU
    
  3. vmstat系統負載

    vmstat 2 5
    # r=4(小于8核*2),us=85%,sy=10%,cs=60000/s,判斷為用戶態SQL查詢導致
    

4.3 數據庫層診斷

  1. SHOW PROCESSLIST定位線程

    SHOW PROCESSLIST;
    # 找到Id=1234對應的線程,User=app_user,Info=目標查詢語句,Time=156秒
    
  2. EXPLAIN執行計劃分析

    EXPLAIN SELECT o.*, u.name FROM orders o 
    JOIN users u ON o.user_id=u.id 
    WHERE o.status='paid' AND o.create_time>'2024-01-01';
    
    +----+-------------+-------+------------+------+---------------+------+---------+------+--------+----------+---------------------------------------------+
    | id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows   | filtered | Extra                                       |
    +----+-------------+-------+------------+------+---------------+------+---------+------+--------+----------+---------------------------------------------+
    |  1 | SIMPLE      | o     | NULL       | ALL  | idx_status    | NULL | NULL    | NULL | 100000 |    10.00 | Using where; Using temporary; Using filesort |
    |  1 | SIMPLE      | u     | NULL       | eq_ref| PRIMARY       | PRIMARY| 4       | o.user_id | 1      |   100.00 |                                             |
    +----+-------------+-------+------------+------+---------------+------+---------+------+--------+----------+---------------------------------------------+
    

    問題點

    • 主表orders未使用索引,全表掃描10萬條記錄
    • 觸發臨時表(Using temporary)和文件排序(Using filesort
  3. SHOW PROFILE階段耗時

    SHOW PROFILE FOR QUERY ...;
    # Sending data階段耗時2.3秒,占總耗時92%,表明大量數據傳輸
    

4.4 優化方案與驗證

  1. 添加復合索引

    ALTER TABLE orders ADD INDEX idx_status_create_time (status, create_time);
    
  2. 優化查詢語句

    -- 避免SELECT *,只查詢必要字段
    SELECT o.order_id, o.total_amount, u.name 
    FROM orders o 
    JOIN users u ON o.user_id=u.id 
    WHERE o.status='paid' AND o.create_time>'2024-01-01' 
    ORDER BY o.create_time DESC 
    LIMIT 20;
    
  3. 驗證執行計劃

    EXPLAIN SELECT ...;
    # type變為range,key使用idx_status_create_time,rows預估1000條,Extra移除臨時表和文件排序
    
  4. CPU使用率驗證

    top -c | grep mysqld
    # %CPU降至20%,查詢響應時間從156秒縮短至0.3秒
    

五、預防措施與日常監控

5.1 建立索引優化機制

  • 定期通過pt-index-usage(Percona Toolkit工具)分析未使用索引
  • 對高頻查詢執行EXPLAIN檢查執行計劃

5.2 開啟慢查詢日志

配置long_query_time=1,通過mysqldumpslow分析慢查詢分布:

# 按查詢時間排序,取前10慢查詢
mysqldumpslow -s t -t 10 /var/log/mysql/slow.log

5.3 自動化監控腳本

編寫Shell腳本定時采集CPU、線程狀態等指標:

#!/bin/bash
DATE=$(date +%Y-%m-%d_%H:%M:%S)
CPU_USAGE=$(top -bn1 | grep 'Cpu(s)' | awk '{print $2}')
THREADS=$(mysql -e "SHOW STATUS LIKE 'Threads_running';" | awk '{print $2}')
echo "$DATE,$CPU_USAGE,$THREADS" >> mysql_monitor.log

總結

MySQL CPU使用率過高的排查需遵循“操作系統層定位進程→數據庫層分析SQL→執行計劃優化→效果驗證”的流程。通過toppidstat等工具鎖定問題進程,利用SHOW PROCESSLISTEXPLAINSHOW PROFILE深入分析SQL執行細節,結合索引優化、查詢重構等手段解決性能瓶頸。實際操作中需注意多維度數據關聯分析,避免單一工具誤判,同時建立常態化監控機制預防問題復現。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/84651.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/84651.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/84651.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Java解析前端傳來的Unix時間戳

在Java中&#xff0c;前端傳遞的 1749571200000 是一個 Unix時間戳&#xff08;毫秒級&#xff09;&#xff0c;表示自1970年1月1日00:00:00 UTC以來經過的毫秒數。以下是兩種常見的解析方式&#xff08;推薦使用Java 8的java.time API&#xff09;&#xff1a; 方法1&#xff…

error report

build/X86_VI_hammer_GPU/mem/ruby/network/garnet/fixed-pipeline/OutputUnit_d.cc: In member function ‘int OutputUnit_d::getVCBufferOccupancy(int)’: build/X86_VI_hammer_GPU/mem/ruby/network/garnet/fixed-pipeline/OutputUnit_d.cc:135:40: error: no matching fu…

本地部署模型 --vLLM + Docker 部署+封裝接口

vLLM的介紹 vLLM的核心特性&#xff1a; 最先進的服務吞吐量 使用PageAttention高效管理注意力鍵和值的內存 量化&#xff1a;GPTQ&#xff0c;AWQ&#xff0c;INT4&#xff0c;INT8和FP8 VLLM的靈活性和易用性體現在以下方面&#xff1a; 具有高吞吐量服務以及各種解碼算法…

每日一博 - JWT 安全實戰指南

文章目錄 Pre引言背景與原理簡介核心安全挑戰傳輸層安全實踐簽名算法與密鑰管理Header 與 Claims 嚴格校驗Token 生命周期管理存儲與前端實踐抗攻擊措施日志與監控附加增強與高級方案小結與建議后續方向 引言&#xff1a;闡述 JWT 的流行與安全重要性背景與原理簡介&#xff1a…

403 Access Denied Tomcat managerapp

提示 403 Access Denied You are not authorized to view this page. By default the Manager is only accessible from a browser running on the same machine as Tomcat. If you wish to modify this restriction, you’ll need to edit the Manager’s context.xml file.…

工業鏡頭選型講解

B站 &#xff1a;道傳科技上位機 觀看教程 一、工業鏡頭介紹 鏡頭的主要作用是 將目標成像在圖像傳感器的光敏面上。 下圖左一的型號為 焦距 50mm 最大光圈為F1.6 鏡頭的像面尺寸為2/3英寸&#xff08;最大能夠兼容CCD芯片尺寸&#xff09; 二、工業鏡頭的分類 鏡頭的…

重構技術奇點的路徑:三智雙融認知大飛躍

結合三智雙融理論認知大飛躍框架重構技術奇點的路徑 構建一個三維修訂框架&#xff1a;首先分析融智學視域下的奇點滲透本質&#xff0c;然后按時間線逐年修訂預言并補充融智學維度&#xff0c;最后提出人機共生的實踐路徑。考慮設計表格對比原預言與修訂后的差異&#xff0c;突…

LabVIEW利用Monte Carlo 工業數據模擬應用

基于LabVIEW 平臺&#xff0c;結合 NI 工業級硬件構建 Monte Carlo 模擬系統&#xff0c;實現工業傳感器數據不確定性分析與設備故障概率預測。通過圖形化編程架構與高性能硬件協同&#xff0c;解決復雜工業場景下的隨機問題量化分析需求&#xff0c;適用于智能制造、能源監控等…

2025年滲透測試面試題總結-天翼電子公司[社招]安全運營崗(題目+回答)

安全領域各種資源&#xff0c;學習文檔&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各種好玩的項目及好用的工具&#xff0c;歡迎關注。 目錄 天翼電子商務有限公司[社招]安全運營崗 1. Web服務加固方案 2. IAST技術解析 3. SCA&#xff08;軟件成分…

Java NIO詳解:新手完全指南

文章目錄 1. NIO簡介1.1 NIO的核心優勢1.2 NIO的適用場景 2. NIO與IO的對比2.1 代碼對比示例2.1.1 傳統IO讀取文件2.1.2 NIO讀取文件 3. NIO核心組件3.1 Buffer&#xff08;緩沖區&#xff09;3.2 Channel&#xff08;通道&#xff09;3.3 Selector&#xff08;選擇器&#xff…

webgl(three.js 與 cesium 等實例應用)之瀏覽器渲染應用及內存釋放的關聯與應用

文章目錄 WebGL 概念1. 紋理&#xff08;Texture&#xff09;&#x1f4cc; 概念&#xff1a;&#x1f9e9; 應用方向&#xff1a;&#x1f4a1; 示例代碼&#xff08;加載一張圖片作為紋理&#xff09;&#xff1a; 2. 緩沖區&#xff08;Buffer&#xff09;&#x1f4cc; 概念…

黑馬點評【緩存】

目錄 一、為什么要使用緩存 二、添加商戶緩存 1.緩存的模型和思路 2.代碼 3.緩存更新策略 Redis內存淘汰機制&#xff1a; 3.1 被動淘汰策略&#xff08;不主動淘汰&#xff0c;僅在查詢時觸發&#xff09; 3.2 主動淘汰策略&#xff08;主動掃描內存&#xff0c;按規則…

【地圖服務限制范圍】

根據你提供的 eb_service_area 表結構&#xff0c;其中有兩個字段與地理坐標相關&#xff1a;latlng 和 limit_latlng。這兩個字段分別用于存儲服務范圍區域的坐標和限制區域的坐標。下面是對這兩個字段的具體分析以及如何使用它們來定義執行范圍。 字段分析 latlng&#xff0…

python數據結構和算法(1)

數據結構和算法簡介 數據結構&#xff1a;存儲和組織數據的方式&#xff0c;決定了數據的存儲方式和訪問方式。 算法&#xff1a;解決問題的思維、步驟和方法。 程序 數據結構 算法 算法 算法的獨立性 算法是獨立存在的一種解決問題的方法和思想&#xff0c;對于算法而言&a…

Linux操作系統-性能優化

1. 基礎工具 top / htop top # 實時查看CPU、內存、進程 htop # 增強版&#xff08;支持鼠標操作&#xff09; 關鍵指標&#xff1a;%CPU&#xff08;CPU占用&#xff09;、%MEM&#xff08;內存占用&#xff09;、LOAD AVERAGE&#xff08;系統負載&#…

如何徹底解決緩存擊穿、緩存穿透、緩存雪崩

一、緩存擊穿 成因&#xff1a;緩存擊穿通常發生在某個熱點數據失效或清空后&#xff0c;大量請求同時涌入后端數據庫&#xff0c;導致數據庫崩潰或宕機。 解決方案&#xff1a; 互斥鎖&#xff1a;在獲取數據時&#xff0c;使用分布式鎖&#xff08;如Redis的分布式鎖&…

JDK 8、JDK 17和JDK 19綜合對比分析

JDK 8、JDK 17和JDK 19在性能、特性、易用性及普及性等方面的綜合對比分析&#xff0c;結合了各版本的核心改進和實際應用場景 目錄 ? 一、性能對比 ? 二、語言與特性演進 &#x1f6e0;? 三、API與功能增強 &#x1f3af; 四、易用性改進 &#x1f4ca; 五、市場普及…

Vue-理解 vuex

一、前言 在開發中大型 Vue 應用時&#xff0c;我們常常會遇到多個組件之間共享數據、通信復雜的問題。例如&#xff1a; 多個組件需要訪問同一個用戶信息&#xff1b;組件之間需要傳遞狀態或事件&#xff1b;數據變更需要同步更新多個組件&#xff1b; 這時&#xff0c;Vue…

【209】VS2022 C++對排好序的vector使用二分查找算法的例子

本文介紹了如何對已經排序的 vector 進行二分法查找。 首先&#xff0c;我們先看一下存儲數據的類&#xff0c;我們假設所有數據的 id 是唯一的&#xff1a; DataItem.h #pragma once #include<string>namespace zc {class DataItem{public:int m_id;std::string m_na…

ABAP 上傳 excel 報表

&#xff08;1&#xff09;先在屏幕上增加上傳文件的按鈕 "屏幕選擇條件" SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE TEXT-001. PARAMETERS : p_source LIKE rlgrap-filename . SELECTION-SCREEN END OF BLOCK b1. 你會發現&#xff0c;上面的代碼只…