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

Laravel导入大Excel至SQL Server时出现物理连接不可用错误

问题分析

这个错误是SQL Server ODBC驱动的会话多路复用(SMux)组件抛出的,核心原因是物理数据库连接已经失效,但代码仍在尝试复用它。第一个工作表导入成功、第二个工作表导入部分数据后失败,大概率是长时间批量操作导致连接被SQL Server主动断开,或是SMux的连接复用机制在大批次数据处理时出现冲突。

解决方案

1. 批量插入前手动重置数据库连接

Laravel默认用长连接,但如果批量操作耗时过久,SQL Server会主动回收闲置或长时间占用的连接。可以在每批数据插入前断开并重新连接:

// 断开旧连接并重新建立
DB::disconnect();
DB::reconnect();

// 执行批量插入
Movement::insert($batchData);

2. 禁用ODBC驱动的SMux功能

SMux是ODBC驱动17+的会话多路复用特性,部分场景下会引发连接异常。修改config/database.php里的SQL Server配置,添加禁用参数:

'sqlsrv' => [
    'driver' => 'sqlsrv',
    'host' => env('DB_HOST', 'localhost'),
    'port' => env('DB_PORT', '1433'),
    'database' => env('DB_DATABASE', 'forge'),
    'username' => env('DB_USERNAME', 'forge'),
    'password' => env('DB_PASSWORD', ''),
    'charset' => 'utf8',
    'prefix' => '',
    'prefix_indexes' => true,
    'options' => [
        PDO::SQLSRV_ATTR_DIRECT_QUERY => true,
        PDO::SQLSRV_ATTR_ENCODING => PDO::SQLSRV_ENCODING_UTF8,
        // 禁用SMux相关特性
        'TrustServerCertificate' => 'yes',
        'ConnectionTimeout' => 60, // 延长连接超时
        'LoginTimeout' => 60,
        'MultipleActiveResultSets' => false,
        'Encrypt' => 'no', // 非必要时关闭加密,避免SMux冲突
    ],
],

3. 调小批量插入的数据量

单批次数据量过大会拉长操作时间,触发连接超时。把每批插入的条数从原有的(比如1000条)降到200-300条:

$batchSize = 200; // 缩小批次规模
$rows = $reader->getSheet($sheetIndex)->getRowIterator();
$batchData = [];

foreach ($rows as $row) {
    $batchData[] = $this->formatRow($row);
    if (count($batchData) >= $batchSize) {
        Movement::insert($batchData);
        $batchData = [];
        // 可选:插入后短暂休眠,降低数据库负载
        usleep(100000); // 休眠100毫秒
    }
}

// 插入剩余的零散数据
if (!empty($batchData)) {
    Movement::insert($batchData);
}

4. 调整SQL Server的连接超时配置

登录SQL Server Management Studio,检查服务器端的连接设置:

  • 右键服务器 -> 属性 -> 连接,把“远程查询超时值”调大(比如设为300秒)
  • 检查数据库连接池的回收策略,避免过早释放活跃连接

5. 用事务包裹批次操作(可选)

如果业务允许,给每批插入加事务,同时在事务完成后重置连接:

foreach ($rows as $row) {
    $batchData[] = $this->formatRow($row);
    if (count($batchData) >= $batchSize) {
        DB::transaction(function () use ($batchData) {
            Movement::insert($batchData);
        });
        $batchData = [];
        // 重置连接
        DB::disconnect();
        DB::reconnect();
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 13:05:19