[Resolved] – MySQL lock wait timeout exceeded using Laravel queues and jobs

Valerio Barbera

Hi, I’m Valerio, software engineer and CTO at Inspector.

One of the most readed article I’ve posted on our blog is related to a queue and jobs configuration in a Laravel application. Queues and Jobs introduces parallel tasks execution in your app that is one of the most interesting field for any developers committed to grow a digital business and it’s also the first step to scale your app keeping server resources cost-friendly.

So I decided to write about some side effects that queues adoption can causes in your application providing possible solutions based on my real life experience.

Use database transactions

One of the most known uses of database transactions is that when an error occurs the transaction can rollback, and any changes you made to the database within that transaction are rolled back as well.

Data Integrity

DB::transaction(function () {
    DB::table('users')->update(['votes' => 1]);


This is a really useful thing when your code needs to update multiple tables and run some complicated task that could produce exceptions. In that case all previous data changes will not be applyed to the database keeping your data consistent with itself.


Another thing database transaction can help us with is “concurrency”.

In a highly concurrent environment (that’s what we want to build) where the application needs to update resources on the database a lot like multiple jobs that want update the same record in the same table, you can handle this situation retrying to execute e blocked transaction:

DB::transaction(function () {
    DB::table('users')->update(['votes' => 1]);

}, 5);

Where the second parameter “5” is the number of times a transaction should be reattempted before close the transaction (rolled back) and thrown the “Lock wait timeout” exception.

After becoming familiar with queues and jobs you risk to see a bunch of exceptions appearing in your log files.

That was my case.

My experience

I was struggling with this issue in a scenario where I needed to update a date-time field in a table called “recently_executed_at” from many concurrent jobs that try to execute the update on the same record in the same time, causing the “lock wait timout” execption as descibed above.

This is not a solution:

DB::transaction(function () use ($project) {
    $task->update(['recently_executed_at' => now()]);
}, 5);

because after attempting the execution for 5 times it throw an exception.

For me was not important to have this field updated with the real last execution time from the last executed job, I just need a reasonable recently timestamp to show in the frontend as additional information.

So if another job is locking the row for update I just want to skip this statement in all others jobs.

Reading and dealing with Pessimistic/Optimistic locking sent me off the road for several days. In such scenario the solution was to deal with “Race Condition” (multiple jobs try to update the same database record at the same time).

In the Laravel documentation you can find the solution in the Cache section as “Atomic Lock”. It took me almost a week of research to understand that the “Atomic Lock” in the Cache driver could solve my problem 🤕 🤕 🤕 .

Final code

Cache::lock("task-{$task->id}-update")->get(function () use ($task) {
    $task->update(['recently_executed_at' => now()]);

It was enough to wrap the update statement in a closure whose execution is conditioned by the LOCK. If the lock isn’t available (another job is executing the update) the code block will be skipped.

Note that you need to create the lock name based on the “record id” to manage the race condition on a specific record at a time and not on entire table.


Running in background it’s really hard to understand if your jobs consume all server resources or generate errors.

You will no longer have immediate feedback like from the result of an http request.

If the job fails he will do it silently, without anyone noticing. That’s exactly why I built Inspector, a simple Code Execution Monitoring to observe your code behavior in real-time.

If background jobs or artisan command are an indispensable component for the operation of your app you can learn more about our application performance monitoring metrics.


Efficiently interact with your database at scale isn’t easy.

Database is a shared resource. We often forget that each request is not independent of other requests.

If one request is slow, it’s unlikely to affect the others… right?

Database is used by all processes that runs in your application. Even just one poorly designed access can hurt the performance of the whole system. So, be careful with thinking “it’s okay if this piece of code isn’t optimized”. One slow database access can strain your database, causing a negative experience to your users.

New to Inspector?

Are you looking for a “code-driven” monitoring tool instead of having to install things at the server level?

Get a monitoring environment specifically designed for software developers avoiding any server or infrastructure configuration.

Thanks to Inspector, you will never have the need to install things at the server level or make complex configuration in your cloud infrastructure to monitor your application in real-time.

Inspector works with a lightweight software library that you can install in your application like any other dependencies. In case of Laravel you have our official Laravel package at your disposal. Developers are not always comfortable installing and configuring software at the server level, because these installations are often managed by external teams, and they are out of the software development lifecycle.

Visit our website for more details: https://inspector.dev/laravel/

Related Posts

How to configure HTTPS in Laravel Homestead

How to enable HTTPS in Laravel Homestead

Hi, I’m Valerio Barbera, software engineer, founder and CTO at Inspector. In this article I’ll show you how to enable HTTPS for your local applications served by Homestead. I met this need because I am working to implement browser notifications for Inspector using Pusher/Beams. But Beams requires that the application be necessarily served over HTTPS.

Laravel cron scheduling and its secrets

Hi, I’m Valerio Barbera, software engineer, founder and CTO at Inspector. Laravel tasks scheduling is one of the most useful features of the framework.The official documentation clearly explains what it is for: In the past, you may have written a cron configuration entry for each task you needed to schedule on your server. However, this

Laravel validation and custom rules in Inspector

Hi, I’m Valerio Barbera, software engineer, founder and CTO at Inspector. Data validation is one of the fundamental features in any application and it is something developers manipulate almost every day. The value a software provides to users is often a function of the quality of data it is able to manage. Laravel ships with

How to build scalable applications

Read the best news, tips and other direct in your inbox