
php 跳转链接在高频点击时(如1分钟内多次点击)仅首次写入数据库,后续请求被浏览器缓存拦截导致跳转成功但无记录——根本原因是默认 302 重定向被浏览器缓存,需强制禁用缓存并使用 307 临时重定向确保每次请求均真实到达服务器。
该问题并非 PHP 或 MySQL 的限制,而是浏览器对 HTTP 重定向响应的缓存策略所致。当脚本执行 header(“Location: …”) 时,PHP 默认发送的是 HTTP 302 Found 状态码。现代浏览器(Chrome、Edge 等)会对 302 重定向进行启发式缓存:若短时间内对同一 URL(如 thisphpfile.php?link=1)发起多次请求,浏览器可能直接复用前一次重定向结果(即跳转到目标地址),而完全跳过向服务器发送第二次请求——这意味着 INSERT 语句根本不会被执行,自然无法写入数据库。
值得注意的是,这种缓存行为具有“会话感知性”:普通窗口内重复点击失效,但无痕模式(全新上下文)可绕过缓存,这正印证了客户端缓存机制的存在,而非服务端逻辑或数据库锁问题。
✅ 正确解决方案是显式控制 HTTP 响应头,从三方面阻断缓存:
- 使用 307 Temporary Redirect(而非 302):307 明确要求客户端必须保持原始请求方法(GET)和请求体,且禁止浏览器缓存该重定向;
- 添加强缓存禁用头:Cache-Control、Expires、Pragma 共同覆盖各类缓存代理与浏览器策略;
- 确保 header() 在任何输出前调用(已隐含在原代码中,但需注意 ob_end_flush() 后不可再有 echo/print)。
修正后的关键重定向段如下:
立即学习“PHP免费学习笔记(深入)”;
// ✅ 强制非缓存、非重用的临时重定向
header('HTTP/1.1 307 Temporary Redirect');
header('Cache-Control: no-cache, no-store, must-revalidate');
header('Expires: Thu, 01 Jan 1970 00:00:00 GMT');
header('Pragma: no-cache');
header('Location: ' . $link_sql, true, 307);
exit; // ⚠️ 务必终止脚本,防止后续代码执行
⚠️ 重要补充说明:
- exit 或 die() 必须紧跟在 header() 之后,避免重定向后继续执行逻辑;
- 原代码中 ob_end_flush() 在重定向前调用是冗余且潜在风险的(可能触发输出,导致 header 失败),建议移除;
- SQL 注入防护仍需加强:当前仅靠字符串匹配 == ‘1’ 不够健壮,推荐改用预处理语句 + 类型校验(如 (int)$link 或白名单数组);
- 时间字段建议使用 MySQL 的 NOW() 函数替代 PHP date(),避免时区/服务器时间偏差。
通过上述调整,每次点击都将真实触发一次服务端请求,确保点击计数与 IP 记录的准确性和实时性。
