backend · 8 read

Why Is MySQL Using 100% CPU? Causes and How to Fix It

MySQL pinned at 100% CPU? Find the queries causing it, fix the real cause instead of upsizing the server, and stop it coming back. A practical diagnosis guide.

When MySQL sits at 100% CPU, the cause is almost never that the server is too small. It is a handful of queries doing far more work than they should: a lookup that turned into a full table scan because an index is missing, a query that suddenly runs thousands of times a minute, or a heavy report that reads an entire table every time it loads. Adding CPU makes the wasteful work finish faster and hides the problem for a few weeks. Finding the query removes the cause.

This guide walks through finding the offending query while it is happening, fixing the real cause, and stopping it from coming back.

How do you find what's using the CPU right now?

Start with what MySQL is doing this second.

See the running queries

SHOW FULL PROCESSLIST;

Look at the Time and State columns. A query that has been running for seconds, or many copies of the same query, is your suspect. On a busy server, filter to what is actually working:

SELECT id, user, db, time, state, LEFT(info, 120) AS query
FROM information_schema.processlist
WHERE command != 'Sleep' AND info IS NOT NULL
ORDER BY time DESC;

Rank statements by total cost

The query that hurts is not always the slowest one. A query that takes 50ms but runs 100,000 times an hour burns more CPU than one that takes two seconds and runs twice. The sys schema ranks by total impact:

SELECT query, exec_count, total_latency, rows_examined_avg
FROM sys.statement_analysis
ORDER BY total_latency DESC
LIMIT 10;

rows_examined_avg is the tell. If a query examines hundreds of thousands of rows to return ten, it is scanning instead of using an index.

Confirm over time with the slow query log

SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 1;

Leave it on for an hour of normal traffic, then summarise:

mysqldumpslow -s t -t 10 /var/log/mysql/slow.log

What actually causes MySQL to hit 100% CPU?

In order of how often they turn out to be the real cause:

A missing index. The single most common cause. Without the right index, MySQL reads every row in the table to find the ones it needs. EXPLAIN your suspect query: a type of ALL means a full table scan.

EXPLAIN SELECT * FROM orders WHERE customer_id = 4471;

A query that got popular. A new feature or a marketing email drives the same query thousands of times a minute. Individually it is fine; in aggregate it saturates the CPU. This is where exec_count in the ranking above matters.

Sorts and temp tables spilling to disk. ORDER BY or GROUP BY on an unindexed column forces MySQL to build a temporary table, and when it is large it lands on disk. EXPLAIN shows Using temporary; Using filesort.

A report reading the whole table. Month-end dashboards that COUNT or aggregate across millions of rows with no supporting index will pin a core every time someone opens them.

A bad plan after the data grew. A query that was fine at ten thousand rows behaves differently at ten million, especially if table statistics are stale. ANALYZE TABLE your_table; refreshes them.

How do you bring the CPU down fast?

When you need relief now:

  1. Identify the query from SHOW FULL PROCESSLIST. Know what it is before you touch it.
  2. Kill a runaway SELECT if it is clearly the culprit and safe to stop:
KILL 20481;

Be cautious with long writes or ALTER statements, because killing them triggers a rollback that has its own cost.

  1. EXPLAIN it and add the missing index. Most 100% CPU incidents end here:
CREATE INDEX idx_orders_customer ON orders (customer_id);
  1. Throttle the source if a single client or job is hammering the same query, until the real fix ships.

How do you stop it from coming back?

Triage buys you the afternoon. These keep the CPU flat:

  • Audit indexes against your real queries. Every frequent WHERE, JOIN, and ORDER BY column should be supported. The complete MySQL performance tuning guide covers how to design them, including the left-prefix rule and covering indexes.
  • Keep the slow query log on with long_query_time = 1 and review it weekly, so a new slow query surfaces before it becomes an incident.
  • Right-size the InnoDB buffer pool. On a dedicated server, innodb_buffer_pool_size should be roughly 70 to 80% of RAM so hot data stays in memory instead of hitting disk and driving CPU.
  • Review queries before they ship. A five-minute EXPLAIN in code review is cheaper than a production incident.

Frequently asked questions

Why is MySQL suddenly using 100% CPU?

Almost always a small number of queries doing far more work than they should, usually because an index is missing and a lookup became a full table scan, or a query started running far more often. A change in data volume or a new deploy is a common trigger. Adding CPU hides it; finding the query removes the cause.

How do I find which query is using the CPU?

Run SHOW FULL PROCESSLIST to see what is executing right now, and query the sys schema view statement_analysis to rank statements by total latency. The slow query log then confirms the worst offenders over time.

Will adding more CPU or RAM fix high MySQL CPU?

Rarely, and only for a while. If the cause is a missing index or a runaway query, a bigger server just runs the same wasteful work faster and you pay more every month. Fix the query first; scale hardware only when the work itself is genuinely necessary.

Is it safe to kill a MySQL query that is using CPU?

Usually yes for a SELECT, which rolls back cleanly with KILL <id>. Be more careful with a long-running write or an ALTER, because killing it triggers a rollback that can itself take time and load. Identify what the query is before you kill it.


Still pinned at 100% and the missing index is not obvious? Finding the real cause under production load is exactly the work I do. See MySQL performance tuning, or read the full MySQL optimization guide first.

Need help with backend?

Let's discuss your project.

Book a discovery call