Laravel Scheduler bị `Has Mutex` khi dùng `withoutOverlapping()`
1. Context
Trong Laravel Scheduler (Kernel), ta có cấu hình:
$schedule->command('email:send')
->everyMinute()
->withoutOverlapping();
Khi kiểm tra lịch chạy trên server:
docker exec -it -w /var/www/html bus-system php artisan schedule:list
Kết quả:
* * * * * php artisan email:send Has Mutex › Next Due: 12 seconds from now
Trong khi đó, nếu chạy thủ công:
docker exec -it -w /var/www/html bus-system php artisan email:send
command vẫn hoạt động bình thường và gửi mail thành công.
2. Nguyên nhân
withoutOverlapping() trong Laravel Scheduler sử dụng cơ chế mutex (lock) để đảm bảo một command không bị chạy đồng thời nhiều lần.
Luồng hoạt động cơ bản:
11:10:00 → scheduler chạy email:send Laravel tạo mutex lock: email:send
11:11:00 → scheduler chạy lại Laravel kiểm tra thấy lock vẫn tồn tại => bỏ qua lần chạy mới
Điều này giúp tránh việc command bị chạy chồng (overlap).
Khi trạng thái hiển thị Has Mutex
Điều này có nghĩa là Laravel đang thấy lock vẫn còn tồn tại, nên scheduler không chạy lại command.
Các nguyên nhân phổ biến
- Command bị kill giữa chừng (crash / Ctrl + C / container restart).
- Server hoặc container restart khi command đang chạy.
- Command chạy lâu hơn chu kỳ scheduler (ví dụ: > 1 phút với
everyMinute()). - Command bị timeout hoặc exception trước khi Laravel kịp release lock.
- Mutex vẫn còn tồn tại trong cache do lỗi runtime hoặc process không kết thúc đúng cách.
Lưu ý quan trọng
-
withoutOverlapping()có thời gian hết hạn mặc định là 1440 phút (24 giờ). -
Nếu command bị crash, lock có thể tồn tại trong thời gian dài cho đến khi:
- hết hạn TTL, hoặc
- được xóa thủ công
3. Cách xử lý tạm thời
Xóa mutex bị kẹt:
docker exec -it -w /var/www/html bus-system php artisan schedule:clear-cache
Nếu thành công:
INFO Deleting mutex for ['/usr/local/bin/php' 'artisan' email:send].
Sau đó test lại scheduler:
docker exec -it -w /var/www/html bus-system php artisan schedule:run -vvv
4. Cách xử lý lâu dài
4.1 Set timeout cho withoutOverlapping
$schedule->command('email:send')
->everyMinute()
->withoutOverlapping(5);
Ý nghĩa:
Nếu command bị kẹt, sau 5 phút lock sẽ tự hết hạn và scheduler có thể chạy lại.
4.2 Gợi ý cấu hình theo thực tế
->withoutOverlapping(5); // command chạy nhanh
->withoutOverlapping(10); // command trung bình
->withoutOverlapping(30); // command xử lý dữ liệu lớn
⚠️ Lưu ý:
- Giá trị quá nhỏ có thể gây overlap thật nếu command chạy lâu hơn TTL.
- Giá trị quá lớn có thể làm scheduler bị “đứng chờ” lâu khi có sự cố.
5. Lưu ý: schedule:list không chứng minh scheduler đang chạy
Lệnh:
php artisan schedule:list
chỉ hiển thị danh sách schedule đã khai báo trong code.
Nó không đảm bảo scheduler đang được hệ thống thực thi.
Cách kiểm tra scheduler thực tế
Trường hợp dùng cron:
* * * * * php artisan schedule:run
Scheduler chỉ chạy khi cron trigger mỗi phút.
Kiểm tra process (Docker):
docker exec -it bus-system ps aux | grep schedule
Hoặc:
docker exec -it bus-system ps aux | grep artisan
⚠️ Lưu ý:
Nếu dùng schedule:run qua cron, process thường chỉ tồn tại rất ngắn → có thể không thấy khi grep.
Khuyến nghị production
- Dùng cron hoặc supervisor đảm bảo scheduler chạy mỗi phút
- Không dùng
-ittrong cron - Có logging cho scheduler để debug
Ví dụ cron:
* * * * * docker exec -w /var/www/html bus-system php artisan schedule:run >> /var/log/scheduler.log 2>&1
6. Kết luận
Has Mutex không phải lỗi queue và cũng không phải lỗi Laravel Scheduler.
Đây là cơ chế bảo vệ của:
withoutOverlapping()
Mục đích: → tránh command chạy trùng trong cùng một thời điểm.
Khi xảy ra vấn đề:
- Command bị crash
- Container restart
- Process bị kill
- Timeout
→ mutex có thể bị giữ lại và khiến scheduler bỏ qua job.
Cách xử lý:
php artisan schedule:clear-cache
và cân nhắc cấu hình:
$schedule->command('email:send')
->everyMinute()
->withoutOverlapping(5);
Đồng thời đảm bảo hệ thống có process scheduler chạy ổn định mỗi phút.
👉 Nếu bạn chưa setup chuẩn production cho Laravel, bạn nên xem bài này để tránh lỗi scheduler + queue: 🔗 Laravel Server Setup: Cron + Supervisor + Queue
Nguồn: atdev.blog - Nơi lập trình viên và người học công nghệ đọc bài hướng dẫn thực chiến, dùng công cụ dev ngay trên trình duyệt. Hoàn toàn miễn phí, không cần đăng ký.
All rights reserved