Как заблокировать базу данных для Laravel `firstOrCreate`? - PullRequest
0 голосов
/ 17 марта 2020

В настоящее время мы сталкиваемся с Duplicate entry QueryException при выполнении следующего кода:

Slug::firstOrCreate([
  Slug::ENTITY_TYPE => $this->getEntityType(),
  Slug::SLUG        => $slug
], [
  Slug::ENTITY_ID   => $this->getKey()
]);

Поскольку метод firstOrCreate с помощью Laravel сначала проверяет, существует ли запись с атрибутами, перед ее вставкой, это исключение никогда не должно происходить. Однако у нас есть приложение с миллионами посетителей и миллионами действий каждый день, и поэтому мы также используем соединение с основной БД с двумя ведомыми устройствами для чтения. Таким образом, возможно, что возникнут некоторые условия гонки.

В настоящее время мы пытались отделить запрос и принудительно установить мастер-соединение для чтения:

 $slugModel = Slug::onWriteConnection()->where([
     Slug::SLUG        => $slug,
     Slug::ENTITY_TYPE => $this->getEntityType()
 ])->first();

 if ($slugModel && $slugModel->entity_id !== $this->getKey()) {
    $class = get_class($this);
    throw new \RuntimeException("The slug [{$slug}] already exists for a model of type [{$class}].");
}

if (!$slugModel) {
   return $this->slugs()->create([
         Slug::SLUG        => $slug,
         Slug::ENTITY_TYPE => $this->getEntityType()
   ]);
}

Однако иногда возникает исключение.

Наш следующий подход заключается в блокировке таблицы перед проверкой чтения и снятии блокировки после записи, чтобы предотвратить любые вставки с таким же фрагментом в результате действий других баз данных между нашим чтением и нашей записью. Кто-нибудь знает как это решить? Я не очень понимаю, как Laravel Pessimisti c Блокировка может помочь решить проблему. Мы используем MySql для нашей базы данных.

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