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

WordPress车辆CSV导入PHP进程超时致网站崩溃求助

WordPress Avada主题下CSV导入脚本无限运行耗尽资源导致网站崩溃

问题背景

反复出现的棘手问题,多次修复后仍复发,最终导致网站崩溃,暂无法确定根源。

环境与场景

  • WordPress网站
  • 主题:Avada
  • 自定义PHP脚本,每3小时从CSV文件导入车辆数据,用于网站车辆搜索功能

已尝试操作

  • 调整导入代码,但因信息不足无法确认是否为代码问题
  • 提升所有PHP资源配置,但脚本进程仍无限运行,最终耗尽服务器资源导致网站崩溃

相关日志截图

日志截图1
日志截图2

自定义导入代码

function fn_import_csv(){
    define('EXECUTION', uniqid());
    echo "Execution ".EXECUTION."<br><br>";
    update_option('inventory_update', current_time('m/d/Y h:i A')); //update settings field
    
    $file = fopen(ABSPATH."inventory/MP7220_website.csv", "r");
    fgetcsv($file); //skip first row
    while (($data = fgetcsv($file)) !== FALSE){
            //check if INSERT or UPDATE
            $rsCheck = array('posts_per_page' => 1, 'post_type' => 'inventory', 'post_status' => 'any', 'meta_query' => array('relation' => 'AND', array('key' => 'stock','value' => $data[1], 'compare' => '=')));
            $arCheck = get_posts($rsCheck);

            $title = $data[4]." ".$data[5]." ".$data[6]." ".$data[10]." ".$data[16];
            
            if(count($arCheck) == 0){ //insert inventory
                echo "<b style='color:#2271b1'>INSERT</b> <i>".$data[1]."</i> - ".$title."<br>";
                $id = wp_insert_post(array('post_title' => $title, 'post_type'=>'inventory', 'post_status' => 'publish'));
                $photosPieces = explode(";", $data[28]);

                $photos = "";
                for($i = 0; $i < count($photosPieces); $i++){
                    $photos .= "<img src='".$photosPieces[$i]."' style='height:100px!important'>";
                }
                add_post_meta($id, 'photos', $photos);
                add_post_meta($id, 'photos_urls', $data[28]);
                add_post_meta($id, 'has_photos', (count($photosPieces) == "1") ? "N" : "Y");
                add_post_meta($id, 'stock', $data[1]);
                add_post_meta($id, 'price', $data[19]);
                add_post_meta($id, 'vin', $data[2]);
                add_post_meta($id, 'newused', $data[3]);
                add_post_meta($id, 'year', $data[4]);
                add_post_meta($id, 'make', $data[5]);
                add_post_meta($id, 'model', $data[6]);
                add_post_meta($id, 'model_code', $data[7]);
                add_post_meta($id, 'body', $data[8]);
                add_post_meta($id, 'transmission', $data[9]);
                add_post_meta($id, 'series', $data[10]);
                add_post_meta($id, 'series_detail', $data[11]);
                add_post_meta($id, 'door_count', $data[12]);
                add_post_meta($id, 'odometer', $data[13]);
                add_post_meta($id, 'engine_cylinder_ct', $data[14]);
                add_post_meta($id, 'engine_displacement', $data[15]);
                add_post_meta($id, 'drivetrain_desc', $data[16]);
                add_post_meta($id, 'color', $data[17]);
                add_post_meta($id, 'interior_color', $data[18]);
                add_post_meta($id, 'description', $data[23]);
                add_post_meta($id, 'features', $data[24]);
                add_post_meta($id, 'city_mpg', $data[25]);
                add_post_meta($id, 'highway_mpg', $data[26]);
                add_post_meta($id, 'engine', $data[31]);
                add_post_meta($id, 'fuel', $data[32]);
                add_post_meta($id, 'execution', EXECUTION);
                add_post_meta($id, 'lock_price_field', "No");
                add_post_meta($id, 'pre_owned', "No");
                add_post_meta($id, '_yoast_wpseo_metadesc', $title." ".$data[17]." for sale. Visit Major World in Long Island City #NY serving Queens, Brooklyn and Bronx #".$data[2]);
            }else{ //update inventory
                $ar = json_decode(json_encode($arCheck), true);
                echo "<b style='color:#4fb347'>UPDATE</b> <i>".$ar[0]["ID"]." - ".$data[1]."</i> - ".$title."<br>";
                $id = $ar[0]["ID"];
                $photosPieces = explode(";", $data[28]);

                $photos = "";
                for($i = 0; $i < count($photosPieces); $i++){
                    $photos .= "<img src='".$photosPieces[$i]."' style='height:100px!important'>";
                }
                wp_update_post(array('ID' => $id, 'post_title' => $title));
                update_post_meta($id, 'photos', $photos);
                update_post_meta($id, 'photos_urls', $data[28]);
                update_post_meta($id, 'has_photos', (count($photosPieces) == "1") ? "N" : "Y");
                update_post_meta($id, 'stock', $data[1]);

                if(get_field("lock_price_field", $id) == "No" || get_field("lock_price_field", $id) == ""){ //only update the price if it is not locked
                    update_post_meta($id, 'price', $data[19]);
                }

                update_post_meta($id, 'vin', $data[2]);
                update_post_meta($id, 'newused', $data[3]);
                update_post_meta($id, 'year', $data[4]);
                update_post_meta($id, 'make', $data[5]);
                update_post_meta($id, 'model', $data[6]);
                update_post_meta($id, 'model_code', $data[7]);
                update_post_meta($id, 'body', $data[8]);
                update_post_meta($id, 'transmission', $data[9]);
                update_post_meta($id, 'series', $data[10]);
                update_post_meta($id, 'series_detail', $data[11]);
                update_post_meta($id, 'door_count', $data[12]);
                update_post_meta($id, 'odometer', $data[13]);
                update_post_meta($id, 'engine_cylinder_ct', $data[14]);
                update_post_meta($id, 'engine_displacement', $data[15]);
                update_post_meta($id, 'drivetrain_desc', $data[16]);
                update_post_meta($id, 'color', $data[17]);
                update_post_meta($id, 'interior_color', $data[18]);
                update_post_meta($id, 'description', $data[23]);
                update_post_meta($id, 'features', $data[24]);
                update_post_meta($id, 'city_mpg', $data[25]);
                update_post_meta($id, 'highway_mpg', $data[26]);
                update_post_meta($id, 'engine', $data[31]);
                update_post_meta($id, 'fuel', $data[32]);
                update_post_meta($id, '_yoast_wpseo_metadesc', $title." ".$data[17]." for sale. Visit Major World in Long Island City #NY serving Queens, Brooklyn and Bronx #".$data[2]);
                update_post_meta($id, 'execution', EXECUTION);
            }
    }//end while
    fclose($file);

    //remove vehicles
    $argsD = array(
            'posts_per_page'  => -1,
            'post_type'       => 'inventory',
            'post_status'     => 'any',
            'suppress_filters' => false,
            'meta_query'    => array(
                'relation'      => 'AND',
                array(
                    'key'       => 'execution',
                    'value'     => EXECUTION,
                    'compare'   => '!='
                )
            ),
    ); 
    $postsDelete = get_posts($argsD);
    echo "<br><br><h4>TO BE DELETED - <i>".EXECUTION."</i></h4>"; //(".count($postsDelete).")
    foreach ($postsDelete as $arD){
        echo "- ".$arD->post_title." ".$arD->ID."<br>";
        wp_delete_post($arD->ID);
    }
    //end remove vehicles
    wp_die(); //necessary to prevent 0 from being printed
    exit();
}//end import CSV

排查方向与解决方案

一、脚本无限运行核心排查点

  1. CSV文件读取异常

    • 检查CSV格式是否存在错误(如换行符不一致、未转义引号),导致fgetcsv无法识别行边界进入死循环。可在循环内添加日志定位异常行:
      static $row_num = 1;
      error_log("Processing row {$row_num}: " . print_r($data, true));
      $row_num++;
      
    • 确认CSV文件路径、权限是否正常,避免文件无法打开或读取异常。
  2. 数据库查询性能瓶颈

    • 每次循环调用get_posts查询库存,未给stock字段建立索引,导致大量重复查询拖慢进程。给wp_postmeta表的meta_key='stock'建立联合索引(meta_key + meta_value)。
    • 删除环节get_posts($argsD)一次性查询所有待删数据,数据量大时占用内存过高,改为分批删除:
      $argsD['posts_per_page'] = 50;
      $page = 1;
      do {
          $argsD['paged'] = $page;
          $postsDelete = get_posts($argsD);
          foreach ($postsDelete as $arD) {
              wp_delete_post($arD->ID, true); // 直接永久删除,跳过回收站
          }
          $page++;
      } while (!empty($postsDelete));
      
  3. WordPress钩子资源消耗

    • wp_insert_post/wp_update_post触发大量主题/插件钩子(如Avada字段处理、Yoast SEO元数据更新),累积消耗资源。导入前临时禁用钩子:
      // 导入前禁用钩子
      remove_all_actions('save_post');
      remove_all_actions('wp_insert_post');
      

二、脚本优化措施

  1. 分批处理数据
    设置批次大小(如50条),避免内存溢出:

    $batch_size = 50;
    $current_batch = 0;
    while (($data = fgetcsv($file)) !== FALSE){
        $current_batch++;
        // 处理当前行逻辑
        if ($current_batch >= $batch_size) {
            wp_cache_flush();
            gc_collect_cycles();
            $current_batch = 0;
        }
    }
    
  2. 替换低效函数

    • 用get_post_meta替代get_field,减少ACF查询开销:
      if (get_post_meta($id, 'lock_price_field', true) == "No" || get_post_meta($id, 'lock_price_field', true) == "") {
          update_post_meta($id, 'price', $data[19]);
      }
      
    • 直接用$arCheck[0]->ID代替json_decode(json_encode($arCheck), true),减少序列化/反序列化操作。
  3. 添加超时控制
    在脚本开头设置执行超时,防止无限运行:

    set_time_limit(300); // 设置5分钟超时,按需调整
    
  4. 日志与监控

    • 替换echo输出为文件日志,避免输出缓冲异常:
      function log_import($message) {
          error_log("[Inventory Import] " . $message . "\n", 3, ABSPATH . 'inventory_import.log');
      }
      // 替换echo为log_import调用
      
    • 监控服务器进程,确认脚本是真的无限循环还是处理速度过慢。

三、环境层面优化

  • 确认PHP的max_execution_time、memory_limit设置是否生效,避免被服务器面板覆盖。
  • 改用系统级Cron替代WP Cron,避免WP Cron依赖网站访问触发导致的脚本重叠执行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 20:54:50