You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP脚本执行至第4次sleep后中断,批量用户导入异常

排查批量用户导入脚本中断与停顿问题

我碰到过好几次类似的批量处理脚本中断的问题,结合你的代码和描述,从几个核心方向帮你分析解决:

1. 优先切换到CLI模式运行脚本

这大概率是导致脚本中途中断的核心原因!如果你是通过网页浏览器访问这个方法来执行导入,web服务器(Apache/Nginx)都会有全局的请求超时限制(比如Apache的Timeout默认是60秒,Nginx的proxy_read_timeout默认60秒),不管PHP的max_execution_time设置多少,服务器都会主动断开长时间运行的请求。

解决方法:

  • 用命令行直接运行脚本(CLI模式),PHP在CLI下默认max_execution_time是0(无限制),也不会受web服务器超时影响。
  • 如果必须通过web触发,先在脚本开头添加:
set_time_limit(0); // 取消PHP执行时间限制
ini_set('memory_limit', '256M'); // 根据需要调整内存限制,比如512M

同时还要修改web服务器的超时配置(比如Apache改Timeout 3600,Nginx改proxy_read_timeout 3600;),但CLI模式是最省心的方案。

2. 排查CSV文件读取的稳定性问题

你提到即使注释数据库和邮件逻辑,只遍历打印也会莫名停顿,这很可能是fgetcsv遇到了格式异常的行(比如字段里包含未转义的换行符、分隔符,或者编码问题),导致fgetcsv卡住无法继续读取下一行。

替换成更稳健的CSV读取方式:

// 替换原有的fopen和while循环
$filename = FCPATH . 'assets/overdracht_users.csv'; // 用FCPATH代替base_url,避免URL访问文件的问题
$file = new SplFileObject($filename);
$file->setFlags(SplFileObject::READ_CSV | SplFileObject::SKIP_EMPTY | SplFileObject::DROP_NEW_LINE);
$file->setCsvControl(';');
$count = 0;

foreach ($file as $mappedData) {
    $count++;
    // 跳过表头行
    if ($count === 1) continue;
    
    // 检查当前行是否有效
    if (empty($mappedData[0])) {
        error_log("Empty email at row {$count}");
        array_push($importFails, $mappedData);
        continue;
    }
    
    // 后续的用户处理逻辑...
}

注意:用FCPATH代替base_url()来读取本地文件,base_url()返回的是HTTP URL,用fopen访问可能会有额外的网络开销或权限问题,直接用服务器本地路径更可靠。

3. 调整休眠逻辑的触发条件

你当前用$count %50 ==0来触发休眠,但$count包含了表头行和未处理的空行,导致休眠时机和实际处理的用户数不匹配。建议用实际成功导入的用户数$totalImported来判断:

// 替换原有的休眠判断
if ($totalImported > 0 && $totalImported % 50 === 0) {
    echo "Processed {$totalImported} users, sleeping for " . $randSleep . " seconds...\n";
    $randSleep = rand(20, 40);
    sleep($randSleep);
    echo "Resuming processing...\n";
}

这样每次处理完50个有效用户才休眠,逻辑更准确。

4. 避免内存泄漏与日志优化

3500条数据虽然不多,但如果$importFails和$mailFails数组持续增大,加上循环中创建的对象未及时回收,可能会触发内存限制导致脚本中断。

优化方案:

  • 定期将错误日志写入文件,清空数组:
// 处理完每100条失败记录后写入文件并清空
if (count($importFails) >= 100) {
    file_put_contents('import_failures.log', print_r($importFails, true), FILE_APPEND);
    $importFails = [];
}
  • 用error_log()代替var_dump()记录运行状态,避免大量输出导致缓冲区阻塞:
// 替换var_dump("count is " . $count);
error_log("Processed row count: {$count}, imported users: {$totalImported}");

5. 添加错误捕获机制

在用户处理逻辑外层包裹try-catch,捕获异常并记录详细信息,方便定位具体哪一行出问题:

try {
    // 从创建$user对象到数据库插入、邮件发送的所有逻辑
} catch (Exception $e) {
    error_log("Error processing row {$count}: " . $e->getMessage() . "\nStack trace: " . $e->getTraceAsString());
    array_push($importFails, $mappedData);
    continue;
}

按照以上步骤调整后,脚本的稳定性应该会大幅提升,先从CLI模式运行开始测试,这是解决中断问题最关键的一步。

内容的提问来源于stack exchange,提问作者Dennis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 07:31:32