Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/laravel/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Laravel 拉威尔';s的悲观锁也会影响其关系模型?_Laravel_Query Builder_Pessimistic Locking - Fatal编程技术网

Laravel 拉威尔';s的悲观锁也会影响其关系模型?

Laravel 拉威尔';s的悲观锁也会影响其关系模型?,laravel,query-builder,pessimistic-locking,Laravel,Query Builder,Pessimistic Locking,假设我有一个查询,它获取一个带有注释的post模型。所以查询应该是这样的 Post::with(['comments'])->get(); 现在,我想像这样实现laravel的悲观锁定 Post::with(['comments'])->sharedLock()->get(); 它还会锁定注释表中的行吗?文件中提到 共享锁防止在提交事务之前修改所选行 文档给出了检索1个没有关系的模型实例的示例。因此,我不清楚它是否也适用于主模型及其关系。因此,在做了一些测试之后,它似乎也锁

假设我有一个查询,它获取一个带有
注释的
post
模型。所以查询应该是这样的

Post::with(['comments'])->get();
现在,我想像这样实现laravel的悲观锁定

Post::with(['comments'])->sharedLock()->get();
它还会锁定注释表中的行吗?文件中提到

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


文档给出了检索1个没有关系的模型实例的示例。因此,我不清楚它是否也适用于主模型及其关系。

因此,在做了一些测试之后,它似乎也锁定了其关系行。这是我的设想

我打开了两个选项卡,第一个选项卡打开了
/locktest1
,另一个选项卡打开了
/locktest2
。第一个运行这样的函数

DB::transaction(function () {
    dump(Post::with(['comments'])->sharedLock()->get());
    sleep(5);
});
DB::transaction(function () {
    dump(Comment::sharedLock()->get(), 'done');
});
而带有
/locktest2
的第二个选项卡指向这样一个函数

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

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

如果您使用的是共享锁,则在事务提交之前,行不会被修改。这并不妨碍阅读。一旦尝试更新以前锁定的资源,锁定就会生效

此外,正如@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();
});

我的直觉说可能不会,但我不确定。您可以使用(['comments'=>function($query){$query->sharedLock();})->sharedLock()->get()执行
Post::操作;
,但我不能说我曾经以这种方式使用过悲观锁定。有趣的是@TimLewis@TimLewis可以确认您的假设。我刚刚在一个新的应用程序上测试了它。我无法确认这种行为。我已经用一个新的Laravel应用程序测试了它。而且在您的示例中,作为一个sh,in/locktest2中不应该有任何延迟ared lock不会阻止读取,在您的示例中,您不会执行任何更新操作。感谢您指出,这是我的疏忽@shock_gone_wildLets说在事务闭包中有两个查询。第一个查询获取一个模型及其所有关系,而第二个查询更新行的一个关系p来自上一个查询。由于它们都在同一个事务关闭中,它会更新吗?还是会被锁定?在我尝试了您的示例之后,我的环境似乎有问题。据我所知,如果我在两个单独的选项卡上运行/test1,然后运行/test2,那么test2将不得不等待/test1完成。但是从我观察到的情况来看EVE,不管任何查询的共享是否被注释,/Test2仍将等待/Test1。我还在PHPMyAdmin上使用MiRADB V.10。对此有什么想法吗?嗯。我正在使用MariaDB V10和NYNDB引擎。您还考虑了-> SydRoCK()->(?);在选择用户?$Upple?> SaveE()必须等待……我的安装也是一样的。我仔细检查,我很确定我考虑了这个可能性。问题不是它不等待事务完成。问题是它等待事务完成,不管是否存在SysDROCK()。(在保持sleep()的同时,/test2仍将等待sleep()完成,直到它最终更新,即使/test1没有强制执行sharedLock()。我在这里遗漏了什么吗?