You need to enable JavaScript to run this app. 使用PHP批量导入CSV至Azure数据库仅写入479条、处理耗时久的问题咨询
优惠活动
大模型
产品
解决方案
定价
更多

使用PHP批量导入CSV至Azure数据库仅写入479条、处理耗时久的问题咨询

根因定位

从现有代码和实际现象(仅入库479条、无报错直接显示完成)拆解,存在以下核心问题:

  • PDO默认错误模式为静默模式,所有SQL执行失败不会抛出异常,编写的catch块完全不会触发,中途的所有报错都会被直接吞掉,脚本会顺顺当当走完所有循环,哪怕从第480条开始全部插入失败,也会正常弹出导入完成的提示。
  • 未使用参数绑定,直接将CSV字段值拼入SQL语句,只要字段中包含单引号(如姓氏O'Neil)、特殊字符、空值,就会直接触发SQL语法错误,且错误被静默吞掉。
  • 未做执行超时适配,PHP默认30秒超时限制、Azure应用服务的资源限制,会导致脚本跑到479条时被强制终止;且Azure默认关闭错误输出,用户看不到超时提示,只会看到中断后的页面误以为流程跑完了。
  • fgetcsv设置1000字节的行长度限制,只要某行CSV内容超过1000字节,就会被截断成错误的字段值,对应插入必然失败。
  • 逐行自动提交的插入方式效率极低,2000行数据的自动提交会大幅拖慢处理速度,更容易触发超时限制。
修复方案
  • 强制开启PDO的异常抛出模式,让所有SQL、连接层面的错误都能被捕获
  • 改为预编译参数绑定模式,预编译语句仅在循环外准备一次,避免逐行重复编译、杜绝特殊字符导致的语法错误
  • 全量导入逻辑包裹在单事务中,一次性提交所有成功的插入,避免逐行提交的性能损耗,同时防止半截脏数据入库
  • 取消脚本执行超时限制,放宽CSV行读取的截断限制
  • 增加逐行错误统计,明确输出成功条数、失败条数及具体原因,不再出现“不知道差了多少条、不知道错在哪”的问题
修正后可直接运行的代码
try {
    $connection = new PDO("sqlsrv:server = tcp:".$SrvName.",1433; Database = ".$DBName, $SQL_USER, $SQL_PASS);
    // 开启异常抛出模式,不再静默吞错误
    $connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    // 开启全局事务
    $connection->beginTransaction();

    // 取消脚本执行超时限制
    set_time_limit(0);
    $successCount = 0;
    $failRecords = [];

    // 循环外预编译插入语句,仅编译一次
    $insertStmt = $connection->prepare("
        INSERT INTO personal (clientId, lastname, ssn) 
        VALUES (?, ?, ?)
    ");

    if (($handle = fopen("personal.csv", "r")) !== FALSE) {
        // 读取长度设为0,不截断长行
        while (($data = fgetcsv($handle, 0, ",")) !== FALSE) {
            // 跳过CSV表头行
            if ($successCount === 0 && strtolower(trim($data[0])) === 'clientid') {
                continue;
            }
            try {
                // 绑定参数插入,自动处理特殊字符
                $insertStmt->execute([
                    trim($data[0]),
                    trim($data[1]),
                    trim($data[2])
                ]);
                $successCount++;
            } catch (PDOException $singleRowError) {
                // 单行错误不中断整体导入,记录错误详情
                $rowIndex = $successCount + count($failRecords) + 2;
                $failRecords[] = "第{$rowIndex}行:".$singleRowError->getMessage();
            }
        }
        fclose($handle);
    }

    // 所有行处理完成后统一提交事务
    $connection->commit();

    // 输出处理结果
    echo "导入流程结束,成功入库 {$successCount} 条记录";
    if (count($failRecords) > 0) {
        echo "<br><br>共 ".count($failRecords)." 条记录插入失败:";
        echo "<pre>".implode("\n", $failRecords)."</pre>";
    }

} catch (PDOException $fatalError) {
    // 遇到连接断开、事务错误等严重问题时,回滚所有未提交数据,避免脏数据
    if ($connection->inTransaction()) {
        $connection->rollBack();
    }
    echo "导入流程中断:" . $fatalError->getMessage();
}
额外排查提示
  • 现有代码只入库479条的最常见原因,是处理到479条时刚好触发PHP30秒默认超时,脚本被平台强制终止;修正代码后可以直观看到所有失败原因(如主键重复、字段长度超限、数据类型不匹配等),无需再盲目猜测。
  • 首次运行建议先把超时设置、行长度设置改完,再跑全量2000行数据,就能得到准确的导入统计结果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.27 01:15:02