我编写了一个Laravel命令,它将派生一些子进程。子进程将通过Eloquent更新数据库。
代码:
<?php
namespace App\Console\Commands;
use App\Console\BaseCommand;
use App\Item;
use Illuminate\Console\Command;
class Test extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'test';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Command description';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
Item::first();
$children = [];
for($i = 0; $i < 5; $i++) {
$pid = pcntl_fork();
if ($pid == -1) {
die('pmap fork error');
} else {
if ($pid) {
$children[] = $pid;
} else {
Item::first(); exit;
}
}
}
foreach ($children as $child) {
pcntl_waitpid($child, $status);
}
}
}
运行我的代码:
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
这背后的原因是什么?以及如何在子进程中通过口才更新MySQL?
附言:
我认为这个问题的原因是,所有子进程都使用从父进程分叉的相同MySQL连接。
如果我在调用fork()之前没有在父进程中调用Item::first
(),
那么它运行良好。(在我的实际用例中,我不能这样做...父进程将在分叉子进程之前使用MySQL做很多事情。
因为在这种情况下,MySQL连接不会在父进程中初始化,所以每个子进程都会自己初始化连接。
那么,如果是这种情况,如何在分叉后为每个子进程初始化新的MySQL连接?
在Laravel中进行进程分叉后,将以下代码放入子进程中,在Laravel 4.2中为我创建了一个稳定的mysql客户端连接:
DB::disconnect();
// we need to clone the database connection of the parent and
// create a new connection as using the original causes protocol errors
$dbconn_child =
[
'driver' => DB::connection()->getConfig('driver'),
'host' => DB::connection()->getConfig('host'),
'port' => DB::connection()->getConfig('port'),
'database' => DB::connection()->getConfig('database'),
'username' => DB::connection()->getConfig('username'),
'password' => DB::connection()->getConfig('password'),
'charset' => DB::connection()->getConfig('charset'),
'collation' => DB::connection()->getConfig('collation'),
'prefix' => DB::connection()->getConfig('prefix'),
'modes' => DB::connection()->getConfig('modes'),
'options' => DB::connection()->getConfig('options'),
];
Config::set('database.connections.DB_CONFIG_CHILD', $dbconn_child);
DB::setDefaultConnection('DB_CONFIG_CHILD');
DB::reconnect();
这将使用与原始连接相同的参数动态创建新连接,然后将子进程切换到新连接并进行连接。
简单地断开并重新连接默认连接会导致类似于OPs结果的各种mysql协议错误。
如果您在database.php中定义了一个具有相等参数的第二个ddbb,并且您在第二个连接中启动了项目::first?
# Primary database connection
'mysql' => [
'driver' => 'mysql',
'host' => 'localhost',
'database' => 'myddbb',
'username' => 'root',
'password' => '',
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
],
# Secondary database connection
'mysql_forConnectChildren' => [
'driver' => 'mysql',
'host' => 'localhost',
'database' => 'myddbb',
'username' => 'root',
'password' => '',
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
],
后来
$item = \DB::connection('mysql_forConnectChildren')->select('select * from Item')->get(1);
我没有测试,但我认为可以工作
由于这一切都是关于连接死亡的,因此只需重新连接到数据库即可解决此问题。
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中测试了这一点,它工作正常。
问题内容: 我是Laravel的新手。我正在开发laravel 5应用程序,并且卡在这里。我有2个这样的模型: 消息和用户之间存在多对多关系,因此给我一个数据透视表: 我有这样的SQL查询: 如何将此查询转换为laravel对等词? 问题答案: 下面的代码解决了我的问题:
我正在创建一个网站。于是,就有了一个表格给用户看。在我的数据库中,我在操作列下存储了0表示挂起,1表示已批准。如果某个用户有0,则此表中显示待定,如果用户有1,则显示已批准。现在我想当有人点击这个挂起按钮时,我想将数据库值更新为1。我尝试了如下。但是,当我点击挂起按钮,它给我这个错误- 而且我无法更新数据库值。 我怎样才能解决这个问题?? 查看页面(AdminPanel.blade.php) 控制
问题内容: 如何更新子查询中也存在的表?我必须分两个阶段进行吗?(创建一个临时表-将选定的数据放入其中,然后更新最终表) 我正在尝试使用每个CTN的网络标签更新invoiceLine表。 最终结果将是: invoiceLine 我有以下表格: invoiceLine ctn network 1234 null 2345 null 3456 null terminal ctn network 123
我正在与Laravel8合作开发我的论坛项目,目前我已经制作了一个用户可以编辑答案的页面。表格如下: 然后在控制器方法中,我添加了以下内容: 以下是实现这一目标的路线: 现在我想重定向用户到这样的网址: 但是,通过此代码,用户将重定向到此url: 那么我如何才能做到这一点呢? 如果你能和我分享你的想法或建议,我将不胜感激... 谢谢
问题内容: 我有以下口才的查询(这是查询的简化版本,其中包含更多s和s,因此是实现此目的的明显回旋方式-该理论很重要): 如您所见,我最早的约会发生在我的约会上或之后。这导致运行单独的查询来获取该日期,然后将该日期用作主查询中的参数。有没有一种雄辩的方法可以将查询嵌入在一起形成一个子查询,因此只有1个数据库调用而不是2个? 编辑: 根据@Jarek的答案,这是我的查询: 这些块使查询中的所有参数突
我在更新google drive上的现有电子表格时遇到了一个问题,没有使用批量更新(现在我甚至不确定是否可能) 我已经有一些数据现有的电子表格,然后我检索文件从谷歌驱动器通过 我很容易通过名称匹配我的文件,然后我只想在创建的文件中更新电子表格。 这里我从匹配名称的文件中获取电子表格,然后我只想把empy表放在那里(例如)。 第一点,我不确定如何正确地“更新”驱动器上的电子表格,因为我无法使用 我不