Sql-server – How to prevent parallel running of SQL Agent jobs

jobssql serversql-server-2016

What would be good ways to design a group of jobs such that they can never run at the same time?

I am looking for a generic concept, like a semaphore, which makes it easier to ensure that some jobs are never running at the same time.

For example, I'm thinking of a "signal table". When a job starts, it sets the signal and at the end, it resets the signal. In addition, every job needs to wait until the signal is set. (How to implement a CPU friendly waiting?) However, when a job crashes, there must then be a solution to automatically reset the signal, otherwise jobs would never start.

We have 4 jobs which are doing various updates, imports, calculations. They all are running by scheduler, and in addition, some of them can also be started manually by super users in case a special run is needed. However, they should not run at the same time, because it often results then in locks or even deadlocks and the database does not properly respond to the users then.

EDIT: It's a data warehouse which is gathering and consolidating data from multiple external data sources. Every job is responsible for another data source, like this:

  • job #1 is running every 15 minutes
  • job #2 every 3 hours
  • job #3 and Job #4 run once per day or have extra runs when started by super users.

Best Answer

Aside from the comments, here's something you can use to accomplish what you're trying to do (since I'm not a fan of reinventing the wheel for locking systems).

You can use the system stored procedure msdb.dbo.sp_help_job to determine if your other jobs are running as the first step in each job. Then from there you can choose what logic you want it to take next when another job is running such as ending the job (if it's on a routine schedule) or implement a mock sleep using WAITFOR DELAY ('00:00:01') -- Sleeps for 1 second, which you can put inside a WHILE loop to recheck job status.

You can call the sp_help_job by passing in the job name:

EXEC msdb.dbo.sp_help_job @Job_name = 'TheJobName'

And you can use the columns current_execution_status and current_execution_step of the procedure's result set, to help you determine when it's safe to run the current job.

There's also some system job tables that might be helpful to you to query as well, which you can read up on in this StackOverflow answer.