Php 排队作业被卡住,表可能已锁定在Laravel中
我正在使用队列在我的Laravel应用程序中发送电子邮件通知。我将数据库用作队列驱动程序,因此有一个Php 排队作业被卡住,表可能已锁定在Laravel中,php,mysql,laravel,queue,Php,Mysql,Laravel,Queue,我正在使用队列在我的Laravel应用程序中发送电子邮件通知。我将数据库用作队列驱动程序,因此有一个jobsDB表,看起来像: id | queue | payload | attempts | reserved_at 我现在在队列中有一堆未发送的消息,但这是第一个造成所有问题的消息:它在尝试列中有255,当我尝试删除phpMyAdmin中的行时,什么也没有发生-它会挂起大约30秒,然后出现一个空白屏幕 在我重新启动MySQL之后,它允许我删除该行,并正确发送所有其他消息 该行的内容(我仔细查
jobs
DB表,看起来像:
id | queue | payload | attempts | reserved_at
我现在在队列中有一堆未发送的消息,但这是第一个造成所有问题的消息:它在尝试
列中有255
,当我尝试删除phpMyAdmin中的行时,什么也没有发生-它会挂起大约30秒,然后出现一个空白屏幕
在我重新启动MySQL之后,它允许我删除该行,并正确发送所有其他消息
该行的内容(我仔细查看了有效负载
字段)在表面上与所有其他行相同
这是正在执行的作业:
public function handle()
{
try {
$this->order->sendOrderConfirmation();
} catch( Exception $e ){
Log::info('Unable to dispatch order confirmation email.', [
'order' => $this->order->id,
'message' => $e->getMessage(),
'code' => $e->getCode(),
'line' => $e->getLine(),
'file' => $e->getFile()
]);
$this->release();
}
}
上面的日志消息在日志中找不到,但我在日志中找到的是:
SQLSTATE[22003]: Numeric value out of range: 1264 Out of range value for column 'attempts' at row 1 (SQL: update `jobs` set `reserved_at` = 1550737859, `attempts` = 256 where `id` = 1638) in /home/truvisi3/public_html/secure/vendor/laravel/framework/src/Illuminate/Database/Connection.php:647
看起来它试图增加尝试次数计数器,但字段限制为255。好的,但为什么这会破坏整个队列,而不仅仅是这个过程?我能做些什么来阻止将来发生这种情况(除了手动更改尝试列的格式以接受大量数据)
编辑:这是作业类
class DispatchOrderConfirmationEmail implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/**
* @var Order
*/
protected $order;
public $tries = 10;
/**
* Create a new job instance.
*
* @param Order $order
*/
public function __construct(Order $order)
{
$this->order = $order;
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
try {
$this->order->sendOrderConfirmation();
} catch( Exception $e ){
$this->release();
}
}
}
您需要定义排队作业的最大尝试次数,否则将无限期地尝试。使用
数据库
驱动程序时,这意味着尝试次数可能超过MySQLTINYINT UNSIGNED
字段的最大值,导致在第256次尝试时引发数据库异常
有两种方法可以做到这一点
启动辅助进程时使用--尝试:
$php artisan队列:工作--尝试=10
或者在作业类上定义$trys
属性:
public$trys=10;
当两者都存在时,$trys
属性优先
最好始终使用--trytes
指定工作进程的最大尝试次数,这样队列中的侦听器、邮件以及使用队列的任何其他内容在多次尝试后最终都会失败,并在对特定作业有意义时使用$trytes
属性覆盖该限制
自定义错误消息未出现在日志中的原因是数据库
队列驱动程序在从队列中弹出作业时更新尝试次数
和保留时间
字段,然后将作业发送给工人类。由于递增尝试次数
会在工作程序运行之前引发未捕获的数据库异常,因此不会调用您的代码。您可以通过向job类添加:$trys=254
来定义最大尝试次数,上周我接受了这个答案,但是,即使我的job类中有$trys=10
,问题现在也再次出现。请告知。@jovan您可以包括作业类和堆栈跟踪的代码吗?请记住,如果您使用的$trys
属性仅适用于该特定类-任何其他排队操作都将有其自己的最大尝试次数,包括排队侦听器或邮件。我已将作业类添加到问题中。至于堆栈跟踪,尝试发送电子邮件时没有记录任何错误。在我提到的255次尝试之后,只有错误。我可以尝试在try/catch循环中记录一些内容,看看下次出现问题时我们是否有进展。@jovan我只想看到错误,以再次检查尝试的作业实际上是同一个类。系统中只有一个作业和一种通知类型(上面的订单确认)。