这类问题我又碰上了一次。PHP 7.4 加了 opcache 之后跑得很快,最近每天下午开始报 Unable to allocate memory for pool,opcache_get_status 里 interned_strings_usage 的 free 变成 0,只有重启 php-fpm 才恢复。

第一反应是「opcache.max_accelerated_files 偏小,缓存频繁淘汰又重填」,验证下来不成立。

排查方向其实有限,先把可能性排一排。opcache.interned_strings_buffer 只有默认的 8M,项目里字符串字面量太多;代码发布后 opcache 没重置,旧脚本占着字符串池不释放;validate_timestamps 开着,每次请求都重新检查文件时间戳。

第一件事是看 opcache 的实际使用情况

php -r 'print_r(opcache_get_status()["interned_strings_usage"]);'

接着把字符串池和文件数上限一起调大

grep -nE 'interned_strings_buffer|max_accelerated_files' /etc/php.d/10-opcache.ini

然后重启 fpm 让新配置生效

systemctl restart php-fpm && php -i | grep -i opcache

发布流程里补一次缓存重置

curl -s http://127.0.0.1/opcache_reset.php

这类改动我都写进变更记录,过两周再出问题时能对上号。

我习惯把每一步的执行时间和结果记在一边,后面复盘省事。

改完先别撤,确认这几项。opcache_get_status 里 interned_strings 的 free 还有三成以上,缓存命中率在 99% 左右,不再出现内存告警。

interned_strings_buffer 调大后要重启才生效,光 reload 不行;上线脚本里带一次 opcache_reset 比改大参数更省事。这类问题最好一次改到位,反复小改反而容易把原因搅混。

作者 9823189