Laravel 8 运行seeder执行DB::unprepared导入大SQL报MySQL server has gone away如何解决
解决方案
方案1:拆分SQL批量执行(最稳妥,无需调整服务配置)
报错核心原因是一次性读取整个大体积SQL文件、单次执行请求过大超过MySQL阈值,拆分分批执行即可解决,Seeder代码修改如下:
public function run() { $path = public_path('sql/cities.sql'); $sqlContent = file_get_contents($path); // 拆分SQL语句,过滤空行和注释行,兼容PHP7+版本 $sqlArr = array_filter(explode(';', $sqlContent), function($sql) { $trimSql = trim($sql); return $trimSql !== '' && substr($trimSql, 0, 2) !== '--'; }); // 分批事务执行,每批执行100条插入语句 foreach (array_chunk($sqlArr, 100) as $chunk) { DB::transaction(function () use ($chunk) { foreach ($chunk as $singleSql) { DB::unprepared(trim($singleSql) . ';'); } }); // 可选:每执行完一批停顿1毫秒,降低数据库压力 usleep(1000); } }
方案2:确认配置生效+补充超时配置
如果不想拆分SQL,需要确认之前修改的配置已经生效,同时补充MySQL超时配置:
- 修改my.ini后必须重启MySQL服务,重启后进入MySQL执行命令
show variables like 'max_allowed_packet';确认数值是否生效,200M对应返回值为209715200 - 在my.ini中新增以下两行超时配置,保存后重启MySQL:
wait_timeout = 600 interactive_timeout = 600
- 修改php.ini的
memory_limit为256M、post_max_size为256M,保存后重启Web服务/PHP-FPM
方案3:直接用MySQL命令行导入(执行效率最高)
本地开发/允许命令行操作的环境下,直接跳过Seeder用原生MySQL命令导入,速度比PHP执行快10倍以上,不会触发超时问题:
mysql -u 你的数据库用户名 -p 你的数据库名 < D:\codes\laravel\arkanlabs_b2b\public\sql\cities.sql
执行后输入数据库密码等待导入完成即可。
内容的提问来源于stack exchange,提问作者Ahmed
相关产品推荐
相关产品推荐

