如何排查导致CPU高占用的MySQL/MariaDB用户、数据库或表?
MariaDB CPU高占用排查:细粒度追踪与优化方案
一、按用户/数据库/表维度统计CPU使用率
1. 利用Performance Schema(原生细粒度监控)
先开启相关监控项(临时生效,需写入my.cnf实现持久化):
-- 开启语句级监控 UPDATE performance_schema.setup_instruments SET ENABLED = 'YES' WHERE NAME LIKE '%statement/%'; UPDATE performance_schema.setup_consumers SET ENABLED = 'YES' WHERE NAME LIKE '%events_statements_%'; -- 若需要按表统计,额外开启表级监控 UPDATE performance_schema.setup_instruments SET ENABLED = 'YES' WHERE NAME LIKE '%table%'; UPDATE performance_schema.setup_consumers SET ENABLED = 'YES' WHERE NAME LIKE '%events_waits_%';
按数据库用户统计CPU占比
SELECT user, ROUND(SUM(timer_wait)/1000000000, 2) AS total_cpu_seconds, ROUND((SUM(timer_wait) / (SELECT SUM(timer_wait) FROM performance_schema.events_statements_summary_by_user_by_event_name)) * 100, 2) AS cpu_percentage FROM performance_schema.events_statements_summary_by_user_by_event_name GROUP BY user ORDER BY total_cpu_seconds DESC;
按数据库统计CPU占比
SELECT db, ROUND(SUM(timer_wait)/1000000000, 2) AS total_cpu_seconds, ROUND((SUM(timer_wait) / (SELECT SUM(timer_wait) FROM performance_schema.events_statements_summary_by_digest)) * 100, 2) AS cpu_percentage FROM performance_schema.events_statements_summary_by_digest WHERE db IS NOT NULL GROUP BY db ORDER BY total_cpu_seconds DESC;
按表统计CPU消耗
SELECT object_name AS table_name, ROUND(SUM(timer_wait)/1000000000, 2) AS total_cpu_seconds FROM performance_schema.events_waits_summary_by_table GROUP BY object_name ORDER BY total_cpu_seconds DESC;
注意:Performance Schema的
timer_wait单位为纳秒,转换为秒更易读;长期运行后可通过TRUNCATE TABLE performance_schema.events_statements_summary_by_user_by_event_name;清理历史数据,避免监控本身消耗资源。
2. 利用sys schema(简化版封装)
MariaDB 10.1+自带sys schema,基于Performance Schema生成更友好的统计结果:
- 按用户查看Top CPU消耗语句类型:
SELECT * FROM sys.user_summary_by_statement_type ORDER BY total_latency DESC; - 按数据库查看Top资源消耗SQL:
SELECT * FROM sys.schema_statistics_with_buffer ORDER BY total_latency DESC;
二、慢查询日志优化(针对“结果不多”的问题)
高CPU往往来自大量快速但频繁执行的短查询,而非少数慢查询,调整慢日志参数捕捉这类请求:
-- 降低慢查询阈值到0.1秒(临时生效,需写入my.cnf持久化) SET GLOBAL long_query_time = 0.1; -- 记录未使用索引的查询(注意过滤系统库,避免日志膨胀) SET GLOBAL log_queries_not_using_indexes = ON;
使用pt-query-digest工具分析慢日志,可按用户、数据库、SQL模板聚合统计CPU消耗:
pt-query-digest /var/log/mariadb/slow.log --filter '$event->{db} =~ /^your_app_db$/ && $event->{user} =~ /^app_user$/'
三、实时定位高CPU线程
- 用
top -H -p $(pidof mariadbd)找到MariaDB进程中CPU占比最高的线程ID(十进制)。 - 对应到MariaDB内部线程,查看正在执行的SQL:
SELECT id, user, db, command, time, state, info FROM information_schema.processlist WHERE id = <线程ID>;
用
SHOW FULL PROCESSLIST;可查看完整SQL语句,避免默认截断。
四、通用优化方向
- 检查缓存有效性:若启用查询缓存,验证命中率
SHOW GLOBAL STATUS LIKE 'Qcache_hits';,低命中率建议关闭(MariaDB 10.1.6+默认关闭),改用应用层缓存(如Redis)。 - 优化索引与执行计划:对高频SQL执行
EXPLAIN,排查全表扫描、索引失效情况;用SHOW INDEX FROM your_table;检查索引覆盖度。 - 控制连接数:查看
SHOW GLOBAL STATUS LIKE 'Threads_connected';,若连接数过高,排查应用端连接池配置,避免无效连接导致线程上下文切换消耗CPU。
内容的提问来源于stack exchange,提问作者nn3112337
相关产品推荐
相关产品推荐

