web-dev-qa-db-ja.com

Laravel lockforupdate(ペシミスティックロック)

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を確認すると、レコードが更新されます(ブラウザー1による60秒のロックトリガー内)

しかし、60秒後、レコードはブラウザ1によって再度変更されました(ポイント100000)

だから私はlockforupdateが使用されていると誤解していますか?それとも間違ってテストしますか?

私が期待したのは、最初の60秒間はブラウザ2によって行が変更されるべきではないということです(ファビコンの読み込みまたはエラースローのある空白のページ?)

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

そして私はいくつかの調査をしましたが、sharedLock(共有モードでロック)とlockForUpdate(更新用)の違いを理解できません

ところで、データベースがinnodbであることを確認しました

8
user259752

これは最終的には機能しますが、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;
        }));
    }
11
user259752