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

使用firstOrCreate仍触发主键重复约束错误的排查请求

问题分析

核心原因

  • 竞态条件:firstOrCreate 执行分为两步——先查询是否存在目标ID的记录,不存在则执行插入。批量处理大量数据时,若多进程/请求同时处理同一ID,会出现第一个进程未完成插入,第二个进程查询无结果后也执行插入,最终触发主键冲突。
  • 数据重复:$transformedData 数组可能包含多个相同ID的条目,循环处理时,首个条目创建成功后,后续条目执行 firstOrCreate 时,查询与插入的间隙仍可能触发重复插入(高并发场景下更明显)。
  • 自增主键潜在隐患:迁移中 $table->id() 创建的是自增主键,手动指定ID插入虽不会直接导致本次报错,但如果数据库自增序列值低于手动插入的ID,后续自动生成ID时可能引发其他冲突。

验证点

  • 用 collect($transformedData)->pluck('id')->duplicates() 排查数组内是否存在重复ID。
  • 检查数据库 car_parts 表是否已存在 id=10232010 的记录,若存在,可能是之前执行时异常中断导致部分数据残留,后续循环再次处理该ID。
解决办法

方案1:提前去重+批量插入(推荐)

先筛选出数据库中不存在的ID,再批量插入,减少数据库交互次数,彻底规避竞态问题:

// 提取所有待插入的ID
$allIds = collect($transformedData)->pluck('id')->toArray();

// 查询数据库中已存在的ID
$existingIds = CarPart::whereIn('id', $allIds)->pluck('id')->toArray();

// 筛选出需要插入的条目
$toBeInserted = collect($transformedData)
    ->filter(fn($item) => !in_array($item['id'], $existingIds))
    ->map(function($item) {
        $itemId = $item['id'];
        unset($item['id']);
        $item['id'] = $itemId;
        return $item;
    })
    ->toArray();

// 批量插入
if (!empty($toBeInserted)) {
    CarPart::insert($toBeInserted);
}

方案2:单条记录的竞态处理

若必须逐条处理,用事务+锁或异常捕获避免冲突:

foreach($transformedData as $item) {
    $itemId = $item['id'];
    unset($item['id']);
    
    try {
        DB::transaction(function () use ($itemId, $item) {
            // 用排他锁避免并发插入
            CarPart::lockForUpdate()->firstOrCreate(['id' => $itemId], $item);
        });
    } catch (\Illuminate\Database\QueryException $e) {
        // 捕获主键冲突异常,跳过重复记录
        if ($e->getCode() == 1062) {
            continue;
        }
        // 抛出其他类型异常
        throw $e;
    }
}

方案3:调整模型与数据库设置(可选)

若长期需要手动指定ID,可关闭自增主键:

  1. 在 CarPart 模型中添加:
public $incrementing = false;
protected $keyType = 'int'; // 若ID是大整数则用'bigint'
  1. 修改迁移文件的主键定义:
// 替换原有的$table->id()
$table->unsignedInteger('id')->primary(); // 或unsignedBigInteger,根据ID类型调整

注意:关闭自增后,所有新增记录必须手动指定ID,否则会触发报错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 22:25:15