Laravel lockforupdate (пессимистическая блокировка)

я пытаюсь понять, как правильно использовать/проверить блокировку для обновления, но я обнаружил, что это не работает так, как я ожидал

это просто тестирование

public function index() {
        return dd(\DB::transaction(function() {
            if (\Auth::guard('user')->check()) {
                $model = \App\Models\User::find(1)->lockForUpdate();
                sleep(60);
                $model->point = 100000;
                $model->save();
            } else {
                $model = \App\Models\User::find(1);
                $model->point = 999;
                $model->save();
            }

            return $model;
        }));
}

я пытаюсь протестировать в 2 браузерах, браузер 1 пользователь вошел в систему, а браузер 2 не вошел в систему, браузер 1 нажал кнопку обновления, затем произойдет блокировка для обновления и сон за 60 секунд до обновления

через 60 секунд я захожу в браузер 2 и нажимаю «Обновить», однако запись не заблокирована, я проверяю phpmyadmin, и запись обновляется (в течение 60 секунд триггер блокировки браузером 1)

но через 60 секунд запись снова была изменена браузером 1 (точка 100000)

так я неправильно понимаю, что lockforupdate используется для? Или я тестирую его неправильно?

я ожидал, что строка не должна быть изменена браузером 2 в течение первых 60 секунд (пустая страница с загрузкой значка или ошибка?)

https://laravel.com/docs/5.2/queries#pessimistic-locking

и я провел некоторое исследование, но до сих пор не могу понять, в чем разница между sharedLock (LOCK IN SHARE MODE) и lockForUpdate (FOR UPDATE)

Кстати, я подтвердил, что база данных - это innodb


person user259752    schedule 01.01.2016    source источник


Ответы (3)


Эта работа, наконец, но до сих пор не понимаю, чем отличаются sharedLock(LOCK IN SHARE MODE) и lockForUpdate(FOR UPDATE)

    public function index() {
        return dd(\DB::transaction(function() {
            if (\Auth::guard('user')->check()) {
                $model = \App\Models\User::lockForUpdate()->find(1);
                sleep(30);
                $model->point = 100000;
                $model->save();
            } else {
                $model = \App\Models\User::lockForUpdate()->find(1);
                $model->point = $model->point + 1;
                $model->save();
            }

            return $model;
        }));
    }
person user259752    schedule 01.01.2016
comment
Из документов: laravel.com/docs/5.2/queries#pessimistic-locking SharedLock блокирует только для записи, lockForUpdate также предотвращает их выбор - person cdarken; 11.11.2016
comment
Блокировки транзакций используются для обработки базы данных между многопользовательским доступом. Если ваш стол заблокирован, другие пользователи не смогут получить к нему доступ. Таким образом, данные управляются должным образом. - person Shankar Thiyagaraajan; 29.12.2016

Итак, это старый вопрос, но я считаю, что мой ответ может прояснить, как работает ->lockForUpdate()

Из документации Laravel:

Общая блокировка предотвращает изменение выбранных строк до тех пор, пока ваша транзакция не будет зафиксирована.

Итак, как написано, блокировка будет активна с момента ее вызова до завершения вашей транзакции.

Запомнить:

->find(1) работает как ->first(), ->get(), ->insert(), ->save() и т. д. – он выполняет запрос.

->lockForUpdate() работает как ->where(), ->select(), join() и т. д. — дополняет запрос, но не выполняет его.

$model = \App\Models\User::find(1)->lockForUpdate(); - вы пытаетесь добавить блокировку после того, как запрос уже выполнен

$model = \App\Models\User::lockForUpdate()->find(1); - вы добавляете блокировку перед выполнением запроса, поэтому блокировка активна до завершения транзакции

Разница в том, что в 1-м сценарии ->lockForUpdate() не выполнялось, когда вы учили, что это было

person NoOorZ24    schedule 09.03.2021

Прочтите эту статью ссылка

Пессимистичная и оптимистичная блокировка в Laravel

  • Общий замок:

    DB::table('users')->where('votes', '>', 100)->sharedLock()->get();
    
  • Блокировка для обновления:

    DB::table('users')->where('votes', '>', 100)->lockForUpdate()->get();
    

Документы Laravel

person Ayman Elshehawy    schedule 09.09.2020