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

Laravel中如何处理并发提交请求避免SQL Server数据库随机报错

Laravel站点并发Excel导入SQL Server随机报错修复方案

核心排查与修复步骤

  • 先抓明确的错误信息,不要盲目调整
    直接查两处日志定位根因:

    1. Laravel日志路径:storage/logs/laravel.log,找报错时的SQL错误码、具体SQL语句
    2. SQL Server端执行以下语句抓最近的死锁、锁超时记录:
      SELECT * FROM sys.dm_tran_deadlocks
      SELECT * FROM sys.dm_os_wait_stats WHERE wait_type LIKE '%LOCK%'
      

    常见错误码对应定向修复方向:

    • 1205:死锁,属于事务锁冲突
    • 1222:锁等待超时,锁粒度过大
    • 08001/08S01:数据库连接异常,连接配置或网络问题
    • 2627/2601:唯一键冲突,并发写入重复数据
  • 修复事务与锁冲突问题(占这类并发报错的80%以上)

    1. 缩短事务生命周期:绝对不要把Excel解析、文件读取、数据校验这类IO/计算逻辑放进数据库事务里,事务里只保留最终的批量写入操作,单事务执行时间控制在1秒以内
    2. 控制批量写入粒度:不要把整份Excel的几万行数据放进单个事务一次性写入,拆分单批次100-500行分批upsert,避免SQL Server自动触发锁升级(行锁升级为表锁)
    3. 优化锁粒度:写入查询中添加WITH (ROWLOCK)提示,强制使用行级锁;给导入查询的筛选字段加非聚集索引,避免全表扫描加大范围锁
    4. 禁止全表删写逻辑:不要用truncate/全表delete+全量insert的方式做导入,改用按主键/唯一键upsert的增量写入逻辑
  • 修复数据库连接配置问题

    1. 打开config/database.php,找到sqlsrv连接配置,将persistent参数设为true,开启持久连接,避免并发请求频繁新建连接耗尽数据库连接配额
    2. 如果站点用了Octane/Swoole/RoadRunner加速,必须配置SQL Server连接池,连接池大小设置为EC2实例CPU核数的2-4倍,禁止连接池大小超过数据库端的最大连接限制
    3. 检查EC2安全组、SQL Server端的连接超时配置,将空闲连接超时设为300秒以上,避免大文件导入过程中连接被中间设备掐断
  • 重构导入逻辑避免资源抢占

    1. 把同步HTTP请求里的导入逻辑全部迁移到Laravel队列异步执行,用户上传文件后直接返回导入中提示,后台排队跑任务,避免长时间占着PHP进程和数据库连接
    2. 给同一张目标表的导入任务加分布式互斥锁,同一时间只允许一个任务写入同一张表,避免硬锁冲突:
      // 导入任务执行前加锁,锁超时时间设为单任务最大执行时长即可
      $lock = Cache::lock('import_lock_' . $targetTableName, 600);
      if (!$lock->get()) {
          // 锁获取失败直接返回提示,不要排队等锁
          throw new \Exception('当前有其他导入任务正在执行,请5分钟后再试');
      }
      try {
          // 执行分批导入逻辑
      } finally {
          $lock->release();
      }
      
    3. 导入专用的队列worker数量不要设置过高,单台EC2实例配置2-4个worker即可,避免并发写入打满数据库IOPS

验证方式

调整完成后,用压测工具模拟2-5个用户同时上传不同Excel文件触发导入,连续压测20次以上无报错,且数据库监控中无死锁、锁等待数量突增的情况即为修复完成。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 08:39:14