现场是这样的。导入数据或者生成报表时脚本中断,报内存不足,调大限制后能跑完,但其他站点开始变慢。

排查方向其实有限,先把可能性排一排。单次处理的数据量超过内存限制;一次性把查询结果全部读入数组;限制给得过大,挤占了同机其他服务。

动手时先确认运行时限制

php -i | grep memory_limit

接着改用分批处理降低峰值

grep -rn 'fetchAll' app/

再往下按站点单独设置限制

grep -n memory_limit /etc/php.d/99-site.ini

等前面都确认过,再验证峰值内存占用

php -r 'echo memory_get_peak_usage(true)/1048576;'

同样的操作我在测试机上先走了一遍,线上只做验证过的部分。

这台环境是别人交接的,不少默认值被动过,只能一项项核。

恢复的判定其实很直接。脚本能完整执行,峰值内存稳定在限制之内,同机其他站点不受影响。

把限制调到无上限等于把风险转移给整台机器;分批查询和流式输出才是处理大数据的正确方式。线上能稳定复现的问题都不算难,难的是只在大流量下才出现的那种。

作者 9823189