Laravel的悲观锁是否也会影响其关系模型?

问题描述

可以说我有一个查询,该查询使用其post模型获得一个comment模型。因此查询应该看起来像这样

Post::with(['comments'])->get();

现在,我想像这样实现laravel的悲观锁定

Post::with(['comments'])->sharedLock()->get();

它还会锁定评论表中的行吗?文档提到,

共享锁可防止在事务提交之前修改选定的行

该文档提供了一个示例,该示例检索没有关系的1个模型实例。所以我不清楚天气是否适用于主要模型及其关系。

解决方法

因此,在进行了一些测试之后,似乎它确实也锁定了其关系行。这是我的情况。

我打开了2个标签,第一个标签打开了/locktest1,另一个标签打开了/locktest2。首先运行这样的功能

DB::transaction(function () {
    dump(Post::with(['comments'])->sharedLock()->get());
    sleep(5);
});

第二个带有/locktest2的标签指向这样的功能

DB::transaction(function () {
    dump(Comment::sharedLock()->get(),'done');
});

sleep放在模拟延迟的第一个函数之后。第二个函数中的第二个参数只是一个指示,让我看看第二个函数是否在第一个函数完成后立即运行。我用/locktest1运行第一个选项卡,稍等片刻,然后用/locktest2运行第二个选项卡。浏览器的两个加载指示器都在此时运行。 5秒后,第一个选项卡完成了其sleep,第二个选项卡完成了之后的注释模型。

,

如果您使用共享锁,则在事务提交之前,行不会被修改。这不会阻止阅读。尝试更新以前锁定的资源后,该锁定就会生效。

另外,由于@Tim Lewis怀疑,默认情况下不会锁定渴望加载的关系。

我将给出两个示例路由,以测试不同的场景。只需在不同的浏览器标签中打开domain.com/test1和domain.com/test2。然后重新加载选项卡1,然后重新加载选项卡2。根据您取消注释的行,您会看到第二个选项卡的加载时间有所不同。

这在我的测试环境中适用于MariaDB版本10。

Route::get('test1',function () {
    \DB::transaction(function () {
        \App\User::with(['comments' => function ($query) {
//            $query->sharedLock();
        }])->sharedLock()->get();
        sleep(15);
    });
});

Route::get('test2',function () {
        $user = \App\User::first();
        $user->first_name = \Str::random(10);
//        $user->save();

        $comment = \App\Comment::sharedLock()->first();
        $comment->created_at = \Carbon\Carbon::now()->addDays(array_rand(range(1,10000)));
//        $comment->save();
});