我使用Laravel5.4作为web应用程序,使用RabbitMQ作为消息队列层,使用Laravel队列工作器。我有两个相关的问题:
临时表
构造函数中有以下表创建代码:
Schema::create('tmp_products', function (Blueprint $table) {
$table->temporary();
$table->integer('id');
$table->string('alias', 255);
$table->string('include', 255)->nullable();
$table->string('exclude', 255)->nullable();
});注意使用
$table->temporary();当该进程的多个实例同时运行时,我得到以下错误:
/var/www/myproject/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOStatement.php:91 : PDOException: SQLSTATE42S01:基表或视图已经存在: 1050表'tmp_products‘已经存在于SQLSTATE42S01中
起初,我认为这个表可能不是临时的,但是我没有在MySQL工作台中看到这个表,所以这是不可能的。
可能多个进程似乎共享连接状态(因为临时表是会话特定的)。代码作为一个Laravel php artisan queue:worker命令运行,由supervisord管理(使用numprocs=3),在htop中我可以看到有三个进程具有唯一的PID,所以我不明白它们如何共享连接状态。
队列-失败的作业
更有趣的是,我使用标志--tries=0运行队列工作器(即不要重试处理消息),因此在job->handle()方法中抛出上述异常之后,消息应该立即被传输到Laravel failed_jobs表,但我看到的是异常的无限循环,消息永远不会离开队列。
所以我想我的问题是:
queue:worker进程如何共享db连接状态?throw new Exception();,则消息会按预期失败。任何帮助都是非常感谢的。
谢谢,
编辑:我弄明白了为什么失败的作业没有进入failed_jobs表。将--tries=0设置为零似乎会使作业永远尝试。将其设置为1修复它。
更新:使用原始PDO时会发生相同的错误:
$pdo = DB::connection()->getPdo();
$pdo->exec("CREATE TABLE tmp_products (id INT NOT NULL, alias VARCHAR(255) NOT NULL, include VARCHAR(255) NULL, exclude VARCHAR(255) NULL, PRIMARY KEY (id));");发布于 2017-07-04 08:35:44
好吧我想明白了。我完全误解了Laravel工人的运作方式。在我的后脑勺里,我以为它们就像apache一样工作--在后台为每一项工作生成一名工人--并在完成后摧毁每一名工人。事实并非如此。每个工作人员依次侦听队列、等待和处理作业。它不会在每个作业上重新创建DB会话。
顺便说一句,这意味着相同的错误可能会影响单个工作人员在其处理的第二个作业上。
所以下一份工作中的临时表仍然存在。现在我只检查一下,如果存在表,就不要重新创建。
谢谢
https://stackoverflow.com/questions/44897233
复制相似问题