最近突然发现一个 Laravel 项目的队列任务没有正常执行,检查发现 laravel.log 日志文件居然短短时间居然有 2G 多,打开后看到错误信息主要如下:
[2024-06-03 10:00:02] production.ERROR: SQLSTATE[22003]: Numeric value out of range: 1264 Out of range value for column 'attempts' at row 1 (SQL: update `queue` set `reserved_at` = 1529143202, `attempts` = 256 where `id` = 569) {"exception":"[object] (Illuminate\\Database\\QueryException(code: 22003): SQLSTATE[22003]: Numeric value out of range: 1264 Out of range value for column 'attempts' at row 1 (SQL: update `queue` set `reserved_at` = 1529143202, `attempts` = 256 where `id` = 569) at /home/username/directory/vendor/laravel/framework/src/Illuminate/Database/Connection.php:664, PDOException(code: 22003): SQLSTATE[22003]: Numeric value out of range: 1264 Out of range value for column 'attempts' at row 1 at /home/username/directory/vendor/laravel/framework/src/Illuminate/Database/Connection.php:483)
[stacktrace]
#0 /home/username/directory/vendor/laravel/framework/src/Illuminate/Database/Connection.php(624): Illuminate\\Database\\Connection->runQueryCallback('update `queue` ...', Array, Object(Closure))
#1 /home/username/directory/vendor/laravel/framework/src/Illuminate/Database/Connection.php(490): Illuminate\\Database\\Connection->run('update `queue` ...', Array, Object(Closure))
#2 /home/username/directory/vendor/laravel/framework/src/Illuminate/Database/Connection.php(423): Illuminate\\Database\\Connection->affectingStatement('update `queue` ...', Array)
#3 /home/username/directory/vendor/laravel/framework/src/Illuminate/Database/Query/Builder.php(2173): Illuminate\\Database\\Connection->update('update `queue` ...', Array)
#4 /home/username/directory/vendor/laravel/framework/src/Illuminate/Queue/DatabaseQueue.php(287): Illuminate\\Database\\Query\\Builder->update(Array)
#5 /home/username/directory/vendor/laravel/framework/src/Illuminate/Queue/DatabaseQueue.php(268): Illuminate\\Queue\\DatabaseQueue->markJobAsReserved(Object(Illuminate\\Queue\\Jobs\\DatabaseJobRecord))
#6 /home/username/directory/vendor/laravel/framework/src/Illuminate/Queue/DatabaseQueue.php(198): Illuminate\\Queue\\DatabaseQueue->marshalJob('default', Object(Illuminate\\Queue\\Jobs\\DatabaseJobRecord))
#7 /home/username/directory/vendor/laravel/framework/src/Illuminate/Queue/Worker.php(244): Illuminate\\Queue\\DatabaseQueue->pop('default')
#8 /home/username/directory/vendor/laravel/framework/src/Illuminate/Queue/Worker.php(220): Illuminate\\Queue\\Worker->getNextJob(Object(Illuminate\\Queue\\DatabaseQueue), 'default')
#9 /home/username/directory/vendor/laravel/framework/src/Illuminate/Queue/Console/WorkCommand.php(101): Illuminate\\Queue\\Worker->runNextJob('database', 'default', Object(Illuminate\\Queue\\WorkerOptions))
#10 /home/username/directory/vendor/laravel/framework/src/Illuminate/Queue/Console/WorkCommand.php(85): Illuminate\\Queue\\Console\\WorkCommand->runWorker('database', 'default')
#11 [internal function]: Illuminate\\Queue\\Console\\WorkCommand->handle()
#12 /home/username/directory/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(29): call_user_func_array(Array, Array)
#13 /home/username/directory/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(87): Illuminate\\Container\\BoundMethod::Illuminate\\Container\\{closure}()
#14 /home/username/directory/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(31): Illuminate\\Container\\BoundMethod::callBoundMethod(Object(Illuminate\\Foundation\\Application), Array, Object(Closure))
#15 /home/username/directory/vendor/laravel/framework/src/Illuminate/Container/Container.php(549): Illuminate\\Container\\BoundMethod::call(Object(Illuminate\\Foundation\\Application), Array, Array, NULL)
#16 /home/username/directory/vendor/laravel/framework/src/Illuminate/Console/Command.php(183): Illuminate\\Container\\Container->call(Array)
#17 /home/username/directory/vendor/symfony/console/Command/Command.php(252): Illuminate\\Console\\Command->execute(Object(Symfony\\Component\\Console\\Input\\ArgvInput), Object(Illuminate\\Console\\OutputStyle))
#18 /home/username/directory/vendor/laravel/framework/src/Illuminate/Console/Command.php(170): Symfony\\Component\\Console\\Command\\Command->run(Object(Symfony\\Component\\Console\\Input\\ArgvInput), Object(Illuminate\\Console\\OutputStyle))
#19 /home/username/directory/vendor/symfony/console/Application.php(946): Illuminate\\Console\\Command->run(Object(Symfony\\Component\\Console\\Input\\ArgvInput), Object(Symfony\\Component\\Console\\Output\\ConsoleOutput))
#20 /home/username/directory/vendor/symfony/console/Application.php(248): Symfony\\Component\\Console\\Application->doRunCommand(Object(Illuminate\\Queue\\Console\\WorkCommand), Object(Symfony\\Component\\Console\\Input\\ArgvInput), Object(Symfony\\Component\\Console\\Output\\ConsoleOutput))
#21 /home/username/directory/vendor/symfony/console/Application.php(148): Symfony\\Component\\Console\\Application->doRun(Object(Symfony\\Component\\Console\\Input\\ArgvInput), Object(Symfony\\Component\\Console\\Output\\ConsoleOutput))
#22 /home/username/directory/vendor/laravel/framework/src/Illuminate/Console/Application.php(88): Symfony\\Component\\Console\\Application->run(Object(Symfony\\Component\\Console\\Input\\ArgvInput), Object(Symfony\\Component\\Console\\Output\\ConsoleOutput))
#23 /home/username/directory/vendor/laravel/framework/src/Illuminate/Foundation/Console/Kernel.php(121): Illuminate\\Console\\Application->run(Object(Symfony\\Component\\Console\\Input\\ArgvInput), Object(Symfony\\Component\\Console\\Output\\ConsoleOutput))
#24 /home/username/directory/artisan(37): Illuminate\\Foundation\\Console\\Kernel->handle(Object(Symfony\\Component\\Console\\Input\\ArgvInput), Object(Symfony\\Component\\Console\\Output\\ConsoleOutput))
#25 {main}
"}
错误的字面原因是 Laravel 队列数据表: jobs 的 attempts 字段是 tinyint 无符号类型,最大值为 255 ,而程序要插入的 attempts 值为 256,超出了字段允许的最大值范围。
根本原因是运行队列任务时,没有指定任务错误的最大重试次数。
最大尝试次数
如果你的一个队列任务遇到了错误,你可能不希望无限制的重试。因此 Laravel 提供了各种方法来指定一个任务可以尝试多少次或多长时间。
指定任务可尝试的最大次数的其中一个方法是,通过 Artisan 命令行上的
https://learnku.com/docs/laravel/10.x/queues/14873#max-job-attempts-and-timeout--tries
开关。这将适用于调度作业的所有任务,除非正在处理的任务指定了最大尝试次数。
因此在运行队列命令时,加上--tries
参数即可,比如:
php artisan queue:work --tries=3