Laravel ошибка: SQLSTATE [23000]: нарушение ограничения целостности: 1062 Повторяющаяся запись (только при запуске в качестве кустарной команды) - PullRequest
0 голосов
/ 29 марта 2020

Я испытываю странную проблему, когда на моем локальном компьютере мой код работает отлично без каких-либо ошибок, но на моем работающем сервере (производственном) я получаю эти ошибки при автоматическом запуске заданий (который идет к CLI вместо через PHP, я полагаю):

SQLSTATE [23000]: нарушение ограничения целостности: 1062 Повторяющаяся запись

... кажется, что это происходит только тогда, когда функция, вызывающая SQL inserts запускается командой "php artisan" (или когда эта команда запускается автоматически сервером / jobs / cronjobs). Вставки выполняются следующим образом:

    $carValues = [
        'name' => $carName,
        'car_id' => $carID,
        'count' => $count
    ];

    if ($car){
        //Record already exists - update it
        $car->fill($carValues);
        $car->save(); //save changes
    } else {
        //Record does not exist - add new record
        $car = Car::create($carValues);
    }

В вышеприведенном примере «имя» имеет уникальный ключ и вызывает ошибки. В основном, если $ car уже не был нулевым перед указанным выше сегментом кода, мы бы сделали обновление, иначе это создаст запись. Это работает все 100% времени на моей локальной машине. Кажется, что каким-то образом только на работающем сервере (при использовании команды php artisan или при запуске команды через CLI / запланированные задания) он работает с этими дублирующимися записями, но не указывает на какой-либо конкретный сегмент кода c ошибки передаются как PDOException от ... / vendor / laravel / framework / src / Illuminate / Database / Connection. php

Действительно запутался в этом. Возможно, есть какой-то способ, чтобы PDOException игнорировал их, поскольку он мешал моим запланированным заданиям работать последовательно, в идеале он должен продолжаться без появления этих ошибок. Опять же - он работает на моем локальном компьютере (на котором работает Homestead / Vagrant box), что соответствует настройке моих онлайн-серверов.

1 Ответ

1 голос
/ 29 марта 2020

Это проблема параллелизма.

Вы испытываете это только в своей производственной среде, потому что именно там вы настроили выполнение заданий в очереди.

Это означает, что может быть несколько задания, которые выполняются одновременно.

Вот так:

  • задание A пытается получить $ car (не существует)
  • задание B пытается получить $ car ( не существует)
  • задание A затем вставляет его в базу данных
  • задание B затем пытается вставить его в базу данных, но не может, потому что оно было вставлено заданием A.

Таким образом, вы должны либо добавить повторы, либо использовать «вставить .. при обновлении дублированного ключа», которое выполняет «обновление или создание» на уровне базы данных.

Даже если laravel имеет встроенную функцию "updateOrCreate", это также небезопасно для параллелизма!

Простое исправление / способ проверить, что это действительно так, - заключить код в

DB::transaction(function () {
    ... your code ....
}, 5);

Который будет повторять транзакцию 5 раз, если она не удалась .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...