用日志定位瓶颈并以配置与 SQL 优化提升响应速度
一 日志体系与关键配置
- PHP-FPM 慢日志:记录执行时间超过阈值的脚本调用栈,用于发现 PHP 层耗时函数、外部调用与逻辑瓶颈。
- PHP 错误日志:捕获致命错误、警告、异常,很多性能问题(如连接失败、重试循环)会先体现在错误日志中。
- Nginx 访问日志:通过请求时间字段(如**$request_time**)快速筛出慢请求,配合条件日志只写入超阈值请求,减少磁盘压力。
- MySQL 慢查询日志:定位拖慢页面的SQL,结合 EXPLAIN 与索引优化见效最快。
建议的阈值与路径(可按业务调整):
- PHP-FPM:request_slowlog_timeout = 1s;slowlog = /var/log/php-fpm/www-slow.log
- PHP:log_errors = On;error_log = /var/log/php-fpm/php-error.log
- Nginx:记录超过 1s 的请求到独立慢日志(见下文配置片段)
- MySQL:slow_query_log = 1;long_query_time = 1(单位秒);slow_query_log_file = /var/log/mysql/mysql-slow.log
二 启用与验证日志
三 从日志到优化的闭环流程
-
步骤 1:用 Nginx 慢日志找出“哪些 URL 最慢”
- 关注字段:rt=$request_time,优先排查 > 1–2s 的端点
- 目的:缩小范围,锁定具体接口/页面
-
步骤 2:用 PHP-FPM 慢日志定位“脚本内哪一段最耗时”
- 关注:堆栈中的函数/方法、外部 HTTP 调用、文件 I/O、循环与递归
- 目的:明确是业务逻辑、外部依赖还是框架初始化导致的瓶颈
-
步骤 3:用 MySQL 慢查询日志找出“拖慢页面的 SQL”
- 方法:对慢日志中的典型 SQL 使用 EXPLAIN 检查扫描方式、索引使用、排序与临时表
- 优化手段:添加/改写索引、避免 SELECT *、优化 JOIN 与子查询、分页优化
-
步骤 4:代码与架构层优化
- 解决 N+1 查询(ORM 预加载或批量查询)
- 引入缓存(如 Redis/Memcached)降低数据库压力
- 合并/压缩静态资源,减少请求次数与阻塞
-
步骤 5:验证与回归
- 复测相同场景,确认慢日志条目减少、P95/P99 延迟下降、吞吐提升
四 常见瓶颈与优化对照表
| 日志来源 |
关键线索 |
典型优化 |
| Nginx 访问日志 |
rt > 1s、高并发下 5xx 增多 |
页面/接口拆分、CDN 与静态化、连接与超时参数调优 |
| PHP-FPM 慢日志 |
堆栈显示在 curl_exec、file_get_contents、外部 API、复杂循环 |
连接池/超时、异步或批处理、缓存结果、算法与 SQL 移到更合适的层 |
| PHP 错误日志 |
连接失败、重试循环、内存不足、类未找到 |
修正配置与依赖、限流与熔断、分批处理与内存优化 |
| MySQL 慢查询日志 |
Query_time 高、Rows_examined 远大于 Rows_sent、Using filesort/temporary |
索引优化、SQL 重写、分页与覆盖索引、InnoDB 缓冲与配置调优 |
五 快速命令清单
- 实时查看 PHP-FPM 慢日志:tail -f /var/log/php-fpm/www-slow.log
- 汇总 Nginx 访问日志中 Top URL:awk ‘{print $7}’ /var/log/nginx/access.log | cut -d’/’ -f1 | sort | uniq -c | sort -nr
- 汇总最慢 SQL(MySQL):mysqldumpslow -s at -t 10 /var/log/mysql/mysql-slow.log
- 检查 SQL 执行计划:EXPLAIN SELECT …
六 进阶与注意事项
- 避免在生产长期开启 Xdebug;使用 Blackfire / New Relic / Datadog APM 做低开销的持续性能剖析与告警。
- 条件日志与采样:Nginx 可用 map 分流;高流量场景可对慢日志做采样或降低阈值,避免磁盘被写满。
- 日志轮转与保留:为 php-fpm、nginx、mysql 配置 logrotate,保留 7–30 天并压缩,防止磁盘撑爆。
- 变更风险控制:调整 request_slowlog_timeout / long_query_time 等阈值后,先灰度观察,再全量上线。