Как атомарно загрузить свежую и обновить существующую модель Eloquent?

#php #laravel #eloquent #concurrency #transactions

#php #laravel #eloquent #параллелизм #транзакции

Вопрос:

В моем коде у меня есть существующая красноречивая модель. Я хочу атомарно:

  • загрузите его новую копию из базы данных и
  • если его состояние соответствует ожидаемому, обновите один столбец.

Я написал следующий код:

 private function getRefreshedAndUpdated(MyEloquentModel $old_model)
{
    $id = $old_model->id;
    $new_model = null;
    DB::transaction(function () use ($id, amp;$new_model) {
        $new_model = MyEloquentModel::lockForUpdate()->find($id);
        if ($new_model->state !== 'READY') {
            throw new Exception('Model not ready');
        }
        $new_model->state = 'UPDATED';
        $new_model->save();
    });
    return $new_model;
}
 

Выполняет ли это то, что я хочу?

В частности, гарантирую ли я, что MyEloquentModel::lockForUpdate()->find($id) :

  • всегда будет извлекать модель свежей из БД (пропуская любой кэш, возможно, заполненный выборкой $old_model ранее)?
  • заблокирует ли он предотвращение каких-либо изменений, например, через $old_model (через pthreads) или базовую запись БД в другом процессе?

Я подозреваю, что так и будет, но это для некоторого критического кода, поэтому нужно перепроверить.

Комментарии:

1. fresh refresh кстати, в модели есть методы and

2. Вы также можете использовать кеш для создания атомарных блокировок .

3. @lagbox Большое спасибо, я знал об их существовании. Однако я не знаю, предлагают ли они гарантии, которые я ищу здесь. Вы знаете?

4. @DigitalDrifter Спасибо. Я ищу что-то более фундаментальное — на уровне БД.