How to Diagnose and Mitigate

MySQL High CPU Usage

DEC 25, 2025 • WRITTEN BY ROMAN AGABEKOV
If your MySQL server suddenly uses 80–100% CPU, the issue is rarely hardware. In most cases, it’s caused by inefficient queries, missing indexes, or configuration mismatches. This guide shows how to identify the exact cause and fix it.

How MySQL uses CPU

MySQL primarily consumes CPU while executing queries, evaluating conditions, performing joins and sorts, and coordinating concurrent sessions. In most production systems, sustained high CPU usage is caused by a small number of inefficient queries executed repeatedly.

High CPU usage is not always a problem. During traffic spikes, maintenance tasks, or cache warm-up, MySQL may legitimately use most available CPU. If latency, errors, and throughput remain stable, intervention is usually unnecessary.

High CPU usage becomes a problem only when it correlates with increased query latency, timeouts, or request queueing.

Common causes of high MySQL CPU usage

High MySQL CPU usage is typically caused by how queries are executed, not by hardware limits. In most production systems, a small number of patterns account for the majority of CPU consumption.

1. Inefficient query execution
The most common cause is queries that process more data than necessary. This includes full table scans, filters applied late in execution, and joins that operate on large intermediate result sets. These patterns force MySQL to evaluate and process many rows, consuming CPU even when queries appear logically simple.

2. Missing or non-selective indexes
When indexes do not exist, are poorly selective, or do not match query access patterns, MySQL cannot efficiently limit the number of rows it examines. As a result, CPU is spent scanning and evaluating rows that could otherwise be skipped.

3. Sorting and aggregation overhead
Queries that use ORDER BY, GROUP BY, or DISTINCT without supporting indexes often trigger CPU-intensive sorting and temporary table creation. This overhead grows quickly as data volume increases and is a frequent cause of sustained CPU pressure.

4. High concurrency amplification
Even moderately expensive queries can saturate CPU when executed concurrently by many sessions. Traffic spikes, background jobs, or poorly controlled parallelism can amplify CPU usage far beyond what a single query would cause on its own.

5. Inefficient execution plans
In some cases, MySQL consumes excessive CPU because it chooses inefficient execution plans. This typically happens when row count estimates are inaccurate due to missing or stale statistics, leading to suboptimal join orders or access paths.

6. Schema and configuration side effects
Less commonly, CPU usage is increased by schema design or configuration choices. Oversized data types, inefficient table layouts, or configuration values that do not match the workload can increase the amount of work MySQL performs per query.

How to diagnose high MySQL CPU usage

Step 1: Confirm CPU usage at the OS level
Before analyzing MySQL internals, confirm that MySQL is actually the process consuming CPU and that the issue is sustained.

Verify that MySQL is the CPU consumer
# On Linux
top -c -p $(pgrep -d',' mysqld)

PID     USER   %CPU  %MEM   TIME+     COMMAND
23891   mysql  187.3 52.1   145:23    /usr/sbin/mysqld
Interpreting the output:
%CPU column:
  • Values over 100% indicate multi-core usage (187.3% means roughly 2 CPU cores are fully utilized)
  • 100% = one full core
  • 400% on a 4-core system = maxed out
  • Compare to your total cores: On an 8-core server, 187% is ~23% of total capacity

If mysqld is consistently > 80% CPU (or >100% on multi-core), it’s a CPU issue → continue to the next step.
If mysqld is < 20% CPU, it’s probably not CPU → check I/O / locks instead.
Step 2: Identify CPU-heavy queries
Once you’ve confirmed that MySQL is consuming significant CPU, the next step is to find which queries are responsible. In most systems, a small number of queries account for most CPU usage.

1) Check currently running queries
SHOW FULL PROCESSLIST;
Example output
Id    User     Host            db        Command  Time  State    Info
1245  app      10.0.1.15:52144  shop_db   Query    87    Running  SELECT * FROM orders WHERE status = 'pending';
1248  app      10.0.1.18:53321  shop_db   Query    79    Running  SELECT * FROM orders WHERE status = 'pending';
1251  app      10.0.1.22:54811  shop_db   Query    76    Running  SELECT * FROM orders WHERE status = 'pending';
1260  app      10.0.1.19:55102  shop_db   Query    61    Running  SELECT * FROM orders WHERE status = 'pending';
Focus on queries that:
  • Stay in the Running or execution-related states
  • Appear multiple times across different connections
  • Run for a long time or restart frequently

This helps identify active contributors during a CPU spike.

2) Find queries that consume the most CPU over time

For sustained CPU usage, short but frequent queries are often the cause. Use Performance Schema to find them:
SELECT
  DIGEST_TEXT,
  COUNT_STAR AS exec_count,
  ROUND(SUM_TIMER_WAIT / 1e12, 2) AS total_cpu_sec
FROM performance_schema.events_statements_summary_by_digest
ORDER BY SUM_TIMER_WAIT DESC
LIMIT 5;
Example output
+--------------------------------------------------------------+------------+----------------+
| DIGEST_TEXT                                                 | exec_count | total_cpu_sec |
+--------------------------------------------------------------+------------+----------------+
| SELECT * FROM orders WHERE status = ?                        |     124382 |        1832.47 |
| SELECT id, user_id FROM sessions WHERE expires_at < ?        |     987214 |        1296.83 |
| UPDATE inventory SET quantity = quantity - ? WHERE sku = ?  |     421995 |         742.19 |
| SELECT COUNT(*) FROM logs WHERE created_at >= ?              |      18492 |         611.34 |
| SELECT * FROM products WHERE category_id = ? ORDER BY name  |      23651 |         488.02 |
+--------------------------------------------------------------+------------+----------------+
Pay attention to queries that:
  • Have high total CPU time (total_cpu_sec field)
  • Run very frequently, even if individual executions are fast
These are usually better optimization targets than a single long-running query.

Releem shows query analytics and the live process list in one dashboard, making it easier to identify CPU-heavy queries without switching between tools.
Step 3: Interpret query states and identify root causes
After identifying the queries contributing to high CPU usage, the next step is to interpret their execution states and understand why they are expensive.

Each query state indicates whether MySQL is actively using CPU or waiting on another resource. Use the table below to map common states to likely root causes and the correct next action.

Key decision point
  • Execution states dominate (Running, Sending data, sorting, temporary tables) → the workload is CPU-bound and CPU time is spent executing queries
  • Waiting states dominate (lock, I/O, or metadata waits) → the slowdown is caused by contention or I/O, not query execution, so investigate locks, disk I/O, or metadata blocking instead of optimizing queries

When execution states dominate, the next diagnostic step is execution plan analysis. For a detailed walkthrough, see how to use EXPLAIN in MySQL.

Focus on these CPU-specific patterns:
  • Access type (type column) - eliminate ALL scans
  • Extra field - address Using filesort and Using temporary
  • Rows examined - reduce through better indexing

Releem automates SQL query optimization and MySQL configuration tuning based on observed CPU usage, query behavior, and execution patterns

Immediate decision: Kill the query or investigate further

Once you’ve identified the queries causing high CPU, decide whether to stabilize the system immediately or continue analysis.

Kill the query if it is clearly runaway, appears many times concurrently, and the system is unstable with timeouts or errors. This is common for accidental full scans, background jobs, or reports that can be safely retried later. In these cases, stop one instance first:
KILL <id>;

Observe CPU and latency for 30–60 seconds before taking further action.

If the query is business-critical, runs continuously, or would immediately restart after being killed, continue investigation instead. When the system remains stable despite high CPU, killing the query usually hides the symptom rather than fixing the problem.

Article by

  • Founder & CEO
    Roman Agabekov has 17 years of experience managing and optimizing MySQL and MariaDB in high-load environments. He founded Releem to automate routine database management tasks like performance monitoring, tuning, and query optimization. His articles share practical insights to help others maintain and improve their databases.
Turn MySQL Pain Into Performance.
Get expert insights, real benchmarks, and practical tuning tips — straight from the team behind Releem.
Monthly newsletter. Zero fluff. All signal.