set_time_limit(0);
$stmt->execute();
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
    fputcsv($out, $row); flush();
}

后台导出全量订单,10 万行左右,页面转 90 秒后返回 504,Nginx 错误日志写着 upstream timed out (110)。这类现象通常不是突然出现的,往前翻半天日志能看到苗头。

追下去是这么回事:导出走的是同步请求,PHP 执行时间和 Nginx 的 fastcgi_read_timeout 都是 60 秒,数据量大时必然超。一次性把结果集读进内存再拼字符串,内存也跟着爆。

这次卡住的地方就在「导出超时 504」这一环,单独把它拎出来验证,别和其他改动混在同一次发布里。权限不要一口气开到最大,先加到够用再往上试,范围小才好收。

把复现步骤压到三条以内,交给同事也能跑出来,才算真的定位清楚。改动写完就同步给同事,下一个人踩同一个坑,成本还是你的。

验证用真实数据走一遍,测试数据太干净,边界情况根本碰不到。

处理上按这个顺序:改成先落任务队列 导出完成后通知下载;必须同步时用流式输出 每批 1000 行 flush 一次;把 fastcgi_read_timeout 和 memory_limit 按实际需要调高 并留出余量。

确认没问题再收工,同样 10 万行导出在 90 秒内完成,浏览器直接拿到文件,日志里没有 504。

作者 9823189