Php 排队作业被卡住,表可能已锁定在Laravel中

Php 排队作业被卡住,表可能已锁定在Laravel中,php,mysql,laravel,queue,Php,Mysql,Laravel,Queue,我正在使用队列在我的Laravel应用程序中发送电子邮件通知。我将数据库用作队列驱动程序,因此有一个jobsDB表,看起来像: id | queue | payload | attempts | reserved_at 我现在在队列中有一堆未发送的消息,但这是第一个造成所有问题的消息:它在尝试列中有255,当我尝试删除phpMyAdmin中的行时,什么也没有发生-它会挂起大约30秒,然后出现一个空白屏幕 在我重新启动MySQL之后,它允许我删除该行,并正确发送所有其他消息 该行的内容(我仔细查

我正在使用队列在我的Laravel应用程序中发送电子邮件通知。我将数据库用作队列驱动程序,因此有一个
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();
        }
    }
}

您需要定义排队作业的最大尝试次数,否则将无限期地尝试。使用
数据库
驱动程序时,这意味着尝试次数可能超过MySQL
TINYINT UNSIGNED
字段的最大值,导致在第256次尝试时引发数据库异常

有两种方法可以做到这一点

启动辅助进程时使用
--尝试

$php artisan队列:工作--尝试=10
或者在作业类上定义
$trys
属性:

public$trys=10;
当两者都存在时,
$trys
属性优先

最好始终使用
--trytes
指定工作进程的最大尝试次数,这样队列中的侦听器、邮件以及使用队列的任何其他内容在多次尝试后最终都会失败,并在对特定作业有意义时使用
$trytes
属性覆盖该限制


自定义错误消息未出现在日志中的原因是
数据库
队列驱动程序在从队列中弹出作业时更新
尝试次数
保留时间
字段,然后将作业发送给工人类。由于递增
尝试次数
会在工作程序运行之前引发未捕获的数据库异常,因此不会调用您的代码。

您可以通过向job类添加:
$trys=254
来定义最大尝试次数,上周我接受了这个答案,但是,即使我的job类中有
$trys=10
,问题现在也再次出现。请告知。@jovan您可以包括作业类和堆栈跟踪的代码吗?请记住,如果您使用的
$trys
属性仅适用于该特定类-任何其他排队操作都将有其自己的最大尝试次数,包括排队侦听器或邮件。我已将作业类添加到问题中。至于堆栈跟踪,尝试发送电子邮件时没有记录任何错误。在我提到的255次尝试之后,只有错误。我可以尝试在try/catch循环中记录一些内容,看看下次出现问题时我们是否有进展。@jovan我只想看到错误,以再次检查尝试的作业实际上是同一个类。系统中只有一个作业和一种通知类型(上面的订单确认)。