Laravel队列异常:首次dispatch()任务消失(Ubuntu+Laravel5.6环境)
嘿,我之前在类似环境下碰到过一模一样的问题!结合你的配置(Ubuntu 16.04、Laravel 5.6、PHP 7.2.4、MySQL 5.7.22),这种首次Tinker会话里dispatch()的任务凭空消失的情况,大概率和Tinker的事务机制或者队列初始化的小坑有关,给你几个亲测有效的排查和解决方向:
1. 先搞定Tinker的事务自动提交问题
Laravel Tinker默认启动时会开启一个数据库事务,而且要等会话结束才会提交/回滚。如果你的首次任务分发是在这个未提交的事务里完成的,那jobs表的记录其实还在事务中,没真正落地到数据库里——这就导致你看不到记录,但第二次dispatch时,事务状态已经变化,所以能正常写入。
快速解决的两种方式:
- 启动Tinker时加
--no-interaction参数,直接禁用自动事务:php artisan tinker --no-interaction - 或者在首次dispatch后,手动在Tinker里执行提交:
DB::commit();
我当时用第一种方法就直接解决了。
2. 再确认队列驱动的配置细节
虽然你说第二次能正常工作,但还是得再核对下配置有没有疏漏:
- 确保
.env里的队列驱动确实是数据库:# Laravel 5.6可能用QUEUE_DRIVER或QUEUE_CONNECTION,都试试 QUEUE_DRIVER=database QUEUE_CONNECTION=database - 确认
jobs和failed_jobs表已经生成:php artisan queue:table php artisan queue:failed-table php artisan migrate
有时候配置缓存会导致Tinker里读取的配置不对,可以顺便清下缓存:
php artisan config:clear
3. 深挖日志和数据库操作记录
你说日志里没相关记录,可以试试把日志级别调高点,抓更详细的信息:
- 在
.env里设置LOG_LEVEL=debug,然后重新启动Tinker分发任务,再去storage/logs/laravel.log里找队列相关的debug日志,说不定能找到任务消失的线索。 - 还可以开启MySQL的通用日志,看看首次dispatch时有没有对应的SQL写入请求。比如在MySQL配置里开启
general_log=1,然后查看日志文件,确认任务插入语句是否执行了。
4. 排查任务类本身的问题
有时候任务类的构造函数或者初始化逻辑里有静默异常,会导致任务在分发时被悄悄丢弃。比如构造函数里依赖的模型不存在,或者有未捕获的错误,Laravel在Tinker环境下可能不会把错误打出来。
建议你先写个极简的测试任务:
<?php namespace App\Jobs; use Illuminate\Bus\Queueable; use Illuminate\Queue\SerializesModels; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; class TestQueueJob implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; public function __construct() { // 空构造,避免依赖问题 } public function handle() { \Log::info('测试任务执行成功!'); } }
然后在Tinker里分发这个任务:dispatch(new App\Jobs\TestQueueJob()),如果这个测试任务首次也消失,那问题就在框架或环境上;如果测试任务正常,那就是你原来的任务类有问题。
5. 检查PHP扩展兼容性
Laravel 5.6要求PHP >=7.1.3,你的7.2.4是符合要求的,但某些缺失的扩展也可能导致这种奇怪的行为。可以检查下必备扩展是否都安装了:
php -m | grep -E "bcmath|ctype|fileinfo|json|mbstring|openssl|pdo|tokenizer|xml"
确保这些扩展都在列表里,如果有缺失,安装后重启PHP服务再试试。
根据我的经验,90%的概率是Tinker的事务问题,用--no-interaction启动Tinker应该就能解决。如果还是不行,再逐个排查上面的方向,应该能找到根源。
内容的提问来源于stack exchange,提问作者ankush981

