若错误提示为“Allowed memory size exhausted”(如Fatal error: Allowed memory size of X bytes exhausted),可通过增加PHP内存限制快速缓解问题。
/etc/php/{版本}/apache2/php.ini(Apache)或/etc/php/{版本}/fpm/php.ini(Nginx+PHP-FPM)。搜索memory_limit参数,将其值从默认的128M或256M调整为更高的数值(如512M或1G),保存后重启Web服务:sudo systemctl restart apache2 # Apache
sudo systemctl restart php{版本}-fpm # PHP-FPM(如php8.1-fpm)
public/index.php)顶部添加:ini_set('memory_limit', '512M');
注意:增加内存限制仅为临时解决方案,需结合后续优化避免依赖。
使用工具定位内存泄漏的具体代码位置,避免盲目优化:
memory_get_usage()和memory_get_peak_usage(),输出当前内存使用量及峰值,对比不同阶段的内存变化,判断是否持续增长:echo '当前内存使用:'.memory_get_usage()/1024/1024.'MB<br>';
echo '内存峰值:'.memory_get_peak_usage()/1024/1024.'MB<br>';
cachegrind文件),查看函数调用栈及内存占用情况,定位高内存消耗的函数或方法。根据检测结果,针对性修复常见的内存泄漏场景:
ObjectA持有ObjectB的实例,ObjectB又持有ObjectA的实例),可使用WeakReference(弱引用)打破循环,或重构代码将对象存储在数组中而非相互引用。unset()清除不再需要的大对象、数组或数据库结果集(如$result->close()关闭数据库游标);对于MySQL查询,确保使用mysqli_free_result()释放结果集内存。LIMIT offset, size)或yield生成器逐行处理,避免一次性加载所有数据到内存:// 使用yield逐行读取
public function getLargeData()
{
$query = Db::table('large_table')->field('id, name')->select();
foreach ($query as $row) {
yield $row;
}
}
config/cache.php)中开启查询缓存,减少重复查询的内存消耗:'query_cache' => [
'type' => 'redis', // 使用Redis作为缓存驱动
'expire' => 3600, // 缓存有效期(秒)
],
with方法预加载关联数据(如User::with('orders')->select()),减少数据库查询次数及内存占用。gc_enable()手动触发垃圾回收(如在脚本关键节点调用),及时回收无引用的对象。通过以上步骤,可逐步定位并解决ThinkPHP在Ubuntu环境下的内存泄漏问题,提升应用的稳定性和性能。