Laravel执行LocalitySeeder分块插入时内存耗尽报错如何解决
问题根因
你遇到的内存溢出报错本质是PHP默认128M内存限制不足以承载你硬编码在Seeder中的9万多条数据:你虽然做了分块插入,但整个9万条数据的大数组在Seeder加载时就已经全部载入内存,后续的分块操作是在数组完全加载后才执行,内存占用峰值已经超过了PHP内存限制。
可行解决方案
- 方案1:临时提升Seeder运行时内存限制(最快生效)
在run方法最开头添加内存配置,仅对本次Seeder运行生效,不会影响全局PHP配置:
public function run() { ini_set('memory_limit', '256M'); // 原有代码 }
- 方案2:优化数据加载逻辑(推荐)
不要把9万多条数据硬编码在Seeder类中,改为将数据存放在独立的CSV/JSON文件中,逐行读取后分块插入,避免一次性加载全量数据到内存:
示例代码:
public function run() { \DB::disableQueryLog(); // 关闭查询日志减少内存占用 $chunkSize = 1000; $tempData = []; // 读取CSV文件,路径可自行调整 $handle = fopen(database_path('seeders/data/localities.csv'), 'r'); while (($row = fgetcsv($handle)) !== false) { $tempData[] = [ 'name' => $row[0], 'city_id' => $row[1], 'created_at' => now()->toDateTimeString(), 'updated_at' => now()->toDateTimeString() ]; if (count($tempData) === $chunkSize) { Locality::insert($tempData); $tempData = []; // 清空临时数组释放内存 } } // 插入剩余不足1000条的数据 if (!empty($tempData)) { Locality::insert($tempData); } fclose($handle); }
- 方案3:调整现有分块参数
你当前array_chunk第三个参数设为true会保留原数组键名,插入操作不需要保留键名,改为false即可,同时可以调小分块大小进一步降低内存峰值:
$chunks = array_chunk($input, 1000, false);
内容的提问来源于stack exchange,提问作者Syed Kounain Abbas Rizvi
相关产品推荐
相关产品推荐

