奋斗
努力

Nginx + PHP-FPM + MySQL部署WordPress后MySQL CPU占用异常如何诊断?

云计算

在 Nginx + PHP-FPM + MySQL 的 WordPress 部署环境中,MySQL CPU 占用异常通常不是单一原因造成的,而是由低效查询、配置不当、缓存缺失或并发请求激增共同导致。以下是系统化的诊断步骤和解决方案:


🔍 一、初步确认问题范围

1. 确认是否真是 MySQL CPU 高

  • 使用 top、htop、vmstat 查看哪个进程占用 CPU 最高。
  • 如果确实是 mysqld 或 mysql 进程 CPU 高,则进入下一步。
  • 排除假象:有时 PHP-FPM 因等待 MySQL 响应而堆积,表现为 PHP CPU 高,但根源在 MySQL。
top -p $(pgrep mysqld)

📊 二、深入分析 MySQL 性能

2. 启用慢查询日志(Slow Query Log)

这是最关键的一步。

配置示例(my.cnf / my.ini):

[mysqld]
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 1        # 超过1秒的查询记录为慢查询
log_queries_not_using_indexes = 1  # 记录未使用索引的查询

重启 MySQL 后生效:

systemctl restart mysql

分析慢查询日志:

# 安装 mysqldumpslow(MySQL 自带工具)
mysqldumpslow -s t -t 20 /var/log/mysql/slow.log

或使用更强大的工具如 Percona Toolkit 的 pt-query-digest:

pt-query-digest /var/log/mysql/slow.log

✅ 重点关注:重复出现的高耗时 SQL、全表扫描、无索引查询。


3. 实时监控当前活跃查询

-- 查看所有正在执行的查询
SHOW FULL PROCESSLIST;

-- 查看最近执行的查询统计(需开启 performance_schema)
SELECT * FROM performance_schema.events_statements_summary_by_digest 
ORDER BY SUM_TIMER_WAIT DESC LIMIT 10;

注意:

  • State 列中 Sending data、Copying to tmp table、Sorting result 表示性能瓶颈。
  • Time 列显示查询执行时间。

4. 检查索引使用情况

对可疑慢查询进行 EXPLAIN 分析:

EXPLAIN SELECT * FROM wp_posts WHERE post_status = 'publish' AND post_type = 'post';

关注字段:

  • type: 是否为 ALL(全表扫描)?理想是 ref、range、const。
  • key: 是否使用了索引?
  • rows: 预估扫描行数,越大越差。
  • Extra: 是否有 Using filesort、Using temporary?

✅ 解决方案:为常用查询字段添加合适索引。

例如:

ALTER TABLE wp_posts ADD INDEX idx_post_status_type (post_status, post_type);

5. 检查表锁与行锁竞争

SHOW ENGINE INNODB STATUSG

重点看:

  • LATEST DETECTED DEADLOCK:死锁信息。
  • SEMAPHORES:线程等待情况。
  • TRANSACTIONS:长时间运行的事务。

如果存在大量锁等待,可能是:

  • 大事务未提交。
  • 缺少索引导致锁升级(从行锁升级为表锁)。
  • 并发写入冲突(如插件频繁更新选项表)。

⚙️ 三、检查 MySQL 配置合理性

6. 关键参数审查(my.cnf)

参数 建议值(根据服务器资源调整) 说明
innodb_buffer_pool_size 物理内存的 50–70% 核心缓冲池,直接影响 I/O 和 CPU
innodb_log_file_size 256M–1G 减少刷盘频率,降低 CPU 开销
innodb_flush_log_at_trx_commit 1(安全)或 2(性能) 1 最安全但 CPU/IO 高;WordPress 可考虑设为 2
query_cache_size 0(MySQL 5.7+ 已废弃) 不推荐使用,反而增加 CPU 开销
tmp_table_size, max_heap_table_size 64M–256M 避免磁盘临时表,减少 CPU 排序开销
thread_cache_size 8–16 减少线程创建开销
join_buffer_size 默认即可,勿过大 过大浪费内存且可能引发 CPU 波动

💡 对于高并发 WordPress,适当放宽 innodb_flush_log_at_trx_commit=2 可显著降低 CPU,但牺牲少量数据安全性(崩溃时最多丢失1秒数据)。


🌐 四、检查 WordPress 层面因素

7. 检查插件与主题

  • 禁用所有插件,测试是否仍高 CPU。
  • 逐个启用插件,定位 culprit。
  • 常见罪魁祸首:
    • 实时搜索插件(如 Relevanssi)
    • 社交分享计数插件(频繁调用外部 API 或写数据库)
    • 备份插件(定时全表扫描)
    • SEO 插件(生成 sitemap 时未分页)

8. 检查 WP-Cron 是否失控

WordPress 内置 WP-Cron 每次页面加载都会触发,可能导致高频小查询累积。

解决方案:

  • 禁用内置 WP-Cron:
    // wp-config.php
    define('DISABLE_WP_CRON', true);
  • 设置系统 cron 每5分钟执行一次:
    */5 * * * * cd /path/to/wp && php wp-cron.php > /dev/null 2>&1

9. 启用对象缓存(Object Cache)

  • 使用 Redis 或 Memcached 缓存数据库查询结果。
  • 安装插件:Redis Object Cache 或 Memcached Object Cache。
  • 配置后端 Redis/Memcached 服务。

✅ 效果:大幅减少重复查询,直接降低 MySQL CPU。


🧪 五、压力测试与验证

10. 模拟真实流量测试

使用工具如 Apache Bench (ab)、wrk 或 k6 模拟并发请求:

ab -n 1000 -c 50 http://your-wordpress-site.com/

观察:

  • MySQL CPU 是否飙升?
  • 慢查询数量是否增加?
  • 响应时间是否恶化?

结合监控工具(如 Prometheus + Grafana、Percona Monitoring and Management)可视化趋势。


🛠️ 六、优化总结清单

类别 行动项
SQL 优化 启用慢查询日志 → 分析 → 加索引 → 重写低效查询
配置调优 调整 innodb_buffer_pool_size、flush_log、tmp_table_size 等
缓存策略 启用对象缓存(Redis/Memcached)、页面缓存(Nginx fastcgi_cache 或插件)
WP 配置 禁用 WP-Cron、清理无用插件、限制自动修订版本
架构扩展 读写分离、分库分表(大型站点)、CDN 静态资源卸载

📈 七、推荐监控工具

  • Percona Monitoring and Management (PMM):免费、功能强大,提供详细 MySQL 指标。
  • Prometheus + Grafana:自定义仪表盘,适合已有基础设施的团队。
  • MySQL Enterprise Monitor:商业方案,适合企业级需求。
  • CloudWatch / AWS RDS Performance Insights:如果使用云托管 MySQL。

✅ 最终建议流程

graph TD
    A[MySQL CPU 高] --> B{确认是 MySQL 进程}
    B -->|是| C[启用慢查询日志]
    C --> D[分析慢查询 & EXPLAIN]
    D --> E[添加索引 / 优化 SQL]
    E --> F[检查 MySQL 配置]
    F --> G[启用对象缓存]
    G --> H[检查 WP 插件与 Cron]
    H --> I[压力测试验证]
    I --> J[持续监控]
    B -->|否| K[排查 PHP/Nginx 问题]

通过以上系统化诊断与优化,绝大多数 WordPress MySQL CPU 异常问题都能被定位并解决。记住:先测量,再优化,避免盲目调整配置。

未经允许不得转载:云服务器 » Nginx + PHP-FPM + MySQL部署WordPress后MySQL CPU占用异常如何诊断?