nginx可通过配置条件日志精准捕获慢sql关联请求:在指定代理路径(如/api/v1/query、/search)的location块中,用$upstream_response_time>2秒+uri正则匹配双条件标记$slow_sql,并结合含$request_time、$upstream_response_time、$uri、$upstream_addr等字段的自定义格式写入独立日志,避免误判客户端侧延迟。

直接配置 Nginx 仅对“响应时间 > 2 秒”且命中特定代理路径(如 /api/v1/query、/search 等疑似执行 SQL 的接口)的请求记录日志,是精准定位慢 SQL 上游调用的有效手段——但需注意:Nginx 本身不解析 SQL,也不知道哪条请求触发了慢查询;它只能基于 URI 特征 + 响应耗时 + 代理行为做前置筛选。所谓“深水区慢 SQL 代理路径”,本质是人为约定的、高概率关联数据库操作的后端转发路径。
一、定义目标代理路径并启用关键日志字段
先确保这些路径明确使用 proxy_pass(而非静态服务),并统一打标。例如:
- 在
location /api/v1/query { ... proxy_pass http://backend_db; }中给该 upstream 起名backend_db - 在
http块中定义含性能字段的日志格式,至少包含:$request_time(总耗时)、$upstream_response_time(后端真实响应耗时)、$upstream_addr(具体后端地址)、$uri(用于识别路径)、$status和$upstream_status(区分失败类型)
示例格式定义:
log_format sql_proxy_log '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" $request_time $upstream_response_time $upstream_addr $uri';二、按路径+耗时双条件启用条件日志
不能只靠 if 判断 $request_time > 2,否则会漏掉因客户端上传慢、SSL 握手长等导致的假阳性。应聚焦 $upstream_response_time ——它才真正反映后端(含 DB)处理耗时:
- 在对应
location块内设置变量标记慢代理请求:set $slow_sql 0;<br>if ($upstream_response_time > 2) { set $slow_sql 1; } - 同时限定仅对该路径生效:
if ($uri ~ ^/api/v1/query|/search|/report$) { set $slow_sql 1; }(注意:两个 if 不叠加,用一个复合判断更稳妥) - 最终在该 location 内写入条件日志:
access_log /var/log/nginx/sql_slow.log sql_proxy_log if=$slow_sql;
三、避免常见陷阱
以下操作会让日志失去诊断价值:
-
混用 $request_time 和 $upstream_response_time:若用
$request_time > 2记录,可能把大文件下载、弱网上传、gzip 压缩卡顿都误判为“SQL 慢”,偏离目标 - 未隔离路径,全站记录:静态资源、图片、前端 JS/CSS 也满足耗时条件,日志爆炸且无意义
-
忽略 upstream_status 和状态码:502/504 高频出现时,
$upstream_response_time接近proxy_read_timeout,说明后端已卡死,此时要查连接池或 DB 负载,而非单条 SQL -
没透传 request_id:日志里只有耗时,没有唯一 ID,无法和应用日志、MySQL slow log 关联。建议在该 location 中加:
proxy_set_header X-Request-ID $request_id;<br>log_format ... $request_id;
四、后续分析必须联动下游
这份日志只是“线索入口”。拿到慢请求后,必须立即做三件事:
- 提取日志中的
$request_id,到 Java/PHP 应用日志里搜,看是否出现PreparedStatement.execute耗时、连接获取超时、事务锁等待等关键词 - 提取
$upstream_addr和时间戳,在对应后端服务器上查其本地访问日志或 APM 追踪(如 SkyWalking),确认是哪台实例、哪个方法拖慢 - 提取
$uri和参数(可扩展日志加$args),结合 MySQL 的slow_log查是否有同参数的慢 SQL,验证索引缺失、未走覆盖索引等问题











