$fp = fopen('counter.log', 'a');
if (flock($fp, LOCK_EX)) {
fwrite($fp, $line . PHP_EOL);
fflush($fp);
flock($fp, LOCK_UN);
}
fclose($fp);
多个进程同时往同一个日志文件追加内容,统计时发现条数比实际少,部分记录互相覆盖。先别急着动参数,把报错原文和时间点记下来,顺序反了容易白折腾。
原因不复杂,打开文件后没有以追加模式写入,或加锁后用了重新打开的新句柄,锁没覆盖到实际写入。
围绕「PHP 文件锁并发」排查时,命令行跑一遍比在面板里点十次有用,面板会替你做掉不少隐式操作。改动写完就同步给同事,下一个人踩同一个坑,成本还是你的。
验证用真实数据走一遍,测试数据太干净,边界情况根本碰不到。能分两步做的操作就别合成一步,中间看一眼返回值,出问题好判断。
报错里带路径的,先去看那个路径在不在、权限对不对。
处理上按这个顺序:用追加模式打开并持有同一句柄;写前加排他锁写完释放;数据量大时改用数据库或消息队列。
改完只确认一件事:并发写入后统计行数与实际请求数一致,没有丢失记录。