Laravel 8 生产环境慢查询日志开启后性能下降严重怎么排查

文章导读
生产环境不建议直接在 Laravel 应用层开启全量慢查询日志,优先使用数据库自带的慢查询日志功能。如果必须使用应用层日志,需改为异步通道并设置合理阈值,避免同步写盘阻塞请求。
📋 目录
  1. 命令速用版
  2. 为什么会这样
  3. 分步处理
  4. 怎么验证是否生效
  5. 常见坑
  6. 常见问题
  7. 参考来源
A A

生产环境不建议直接在 Laravel 应用层开启全量慢查询日志,优先使用数据库自带的慢查询日志功能。如果必须使用应用层日志,需改为异步通道并设置合理阈值,避免同步写盘阻塞请求。

先说结论:Laravel 应用层记录慢查询属于同步 I/O 操作,高并发下会显著增加请求耗时,生产环境应优先启用 MySQL 原生慢查询日志。

  • 先定位:确认日志是写在应用层文件还是数据库层,检查是否阻塞主线程
  • 先做:关闭应用层查询监听,改用数据库原生慢查询日志或 APM 工具
  • 再验证:观察接口平均响应时间和服务器 I/O 等待率是否回落

命令速用版

# 检查 MySQL 慢查询日志状态
mysql -u root -p -e "SHOW VARIABLES LIKE 'slow_query_log';"

# 临时开启 MySQL 慢查询日志(无需重启)
mysql -u root -p -e "SET GLOBAL slow_query_log = 'ON';"

# 查看 Laravel 日志文件实时增长情况
tail -f storage/logs/laravel.log

为什么会这样

Laravel 应用层记录查询日志默认在主线程同步执行,每次数据库请求完成后都会触发写文件操作。

在高并发场景下,频繁的磁盘 I/O 会阻塞 PHP 进程,导致请求排队。数据库原生的慢查询日志由数据库进程异步写入,对应用性能影响较小。

分步处理

步骤 1:确认日志实现方式

检查 `app/Providers/AppServiceProvider.php` 的 `boot` 方法中是否有 `DB::listen` 代码。如果有,这段代码会在每个查询结束后执行,包含日志写入逻辑。

步骤 2:关闭应用层查询监听

Laravel 8 生产环境慢查询日志开启后性能下降严重怎么排查

在生产环境配置中注释掉 `DB::listen` 相关代码,或增加环境判断仅在本地生效。

// 修改前
DB::listen(function ($query) { ... });

// 修改后
if (app()->environment('local')) {
    DB::listen(function ($query) { ... });
}

步骤 3:启用数据库原生慢查询

修改 MySQL 配置文件 `my.cnf` 或通过命令设置 `slow_query_log` 为 ON,设置 `long_query_time` 阈值(例如 1 秒)。

步骤 4:引入异步日志或 APM(可选)

如果必须保留应用层日志,配置 Monolog 使用异步处理器,或接入 SkyWalking、Pinpoint 等 APM 工具进行性能监控。

怎么验证是否生效

观察 Laravel 日志文件 `storage/logs/laravel.log` 是否停止增长。使用压测工具或监控面板查看接口平均响应时间(RT)是否下降。检查服务器 `iostat` 命令输出,确认 I/O 等待率降低。

常见坑

1. 日志文件未轮转:慢查询日志可能快速增长占满磁盘,需配置 logrotate。

Laravel 8 生产环境慢查询日志开启后性能下降严重怎么排查

2. 阈值设置过低:将正常查询误判为慢查询,导致日志量过大。

3. 权限问题:MySQL 慢查询日志文件路径需确保 mysql 用户有写入权限。

常见问题

Laravel 自带慢查询日志配置吗?

Laravel 框架本身没有直接的慢查询日志配置项,通常通过 `DB::listen` 事件监听实现。

生产环境能用 Telescope 监控查询吗?

不建议,Telescope 设计用于调试环境,生产环境开启会消耗大量资源且存在安全风险。

异步日志能完全消除性能影响吗?

不能,异步日志仅减少阻塞时间,仍会消耗 CPU 和 I/O 资源,优先推荐数据库原生日志。

参考来源

Laravel Documentation - Database: Query Logging
MySQL Documentation - The Slow Query Log