作者:王立君淑霖_189 | 来源:互联网 | 2022-12-10 10:01
我写了一个Laravel Command,它会分叉一些子进程.子进程将通过Eloquent更新数据库.
码:
运行我的代码:
vagrant@homestead:~/ECAME$ php artisan test
[Illuminate\Database\QueryException]
Packets out of order. Expected 1 received 116. Packet size=6255201 (SQL: select * from `items` where `items`.`deleted_at` is null limit 1)
[Illuminate\Database\QueryException]
Packets out of order. Expected 1 received 100. Packet size=6238815 (SQL: select * from `items` where `items`.`deleted_at` is null limit 1)
[Illuminate\Database\QueryException]
Packets out of order. Expected 1 received 0. Packet size=2816 (SQL: select * from `items` where `items`.`deleted_at` is null limit 1)
[Illuminate\Database\QueryException]
Packets out of order. Expected 1 received 116. Packet size=6381412 (SQL: select * from `items` where `items`.`deleted_at` is null limit 1)
[ErrorException]
Packets out of order. Expected 1 received 100. Packet size=6238815
[ErrorException]
Packets out of order. Expected 1 received 116. Packet size=6381412
[ErrorException]
Packets out of order. Expected 1 received 116. Packet size=6255201
[ErrorException]
Packets out of order. Expected 1 received 0. Packet size=2816
这背后的原因是什么?以及如何在子进程中通过Eloquent更新MySQL?
PS:
我认为这个问题的原因是,所有子进程都使用从父进程分叉的相同MySQL连接.
如果我在调用Item::first()
之前没有调用父进程fork()
,那么它运行良好.(在我的实际用例中,我不能这样做......在fork子进程之前,父进程将对MySQL做很多事情.)
因为在这种情况下,MySQL连接不会在父进程中初始化,因此每个子进程都将自己初始化连接.
那么,如果是这种情况,如何在分叉后为每个子进程初始化一个新的MySQL连接?
1> GiamPy..:
由于它是关于连接死亡的全部,您可以通过简单地重新连接到数据库来解决这个问题.
use Illuminate\Support\Facades\DB;
[...]
public function handle()
{
User::first();
$children = [];
for ($i = 0; $i <5; $i++)
{
$pid = pcntl_fork();
if ($pid == -1)
{
die('pmap fork error');
}
else
{
if ($pid)
{
$children[] = $pid;
}
else
{
DB::connection()->reconnect(); // <----- add this
User::first(); exit;
}
}
}
foreach ($children as $child)
{
pcntl_waitpid($child, $status);
}
}
我在Laravel 5.6中测试了这个并且它可以工作.