Running two sql server jobs into a single job not working - sql

we have a sql server agent job which is running two sql servant jobs.The job is designed in the way that the second job will wait till the first job completed. But sometimes the wait is not working and it causes both jobs ends up running at same time. This causes failure of both jobs. We uses below code for waiting mechanism.
WHILE
(
SELECT COUNT(*) AS cnt
FROM msdb.dbo.sysjobs J
INNER JOIN msdb.dbo.sysjobactivity JA
ON J.job_id = JA.job_id
WHERE start_execution_date IS NOT NULL
AND stop_execution_date IS NULL
AND J.name = "first job name"
AND last_executed_step_date > DATEADD(DD,-1,GETDATE())--//Added to bypass historical corrupt data
) > 0
BEGIN
--WAIT
WAITFOR DELAY '00:01';
END
any suggestion why this is not working sometimes?

Related

SQL Server - keep restarting EXEC as long as dependent job completes

I need to automate element in my backups schedule for differential copies.
DIFF must be performed only when job_a is not running.
The only moment when below code clashes with job_a is when job_a may be still running in scheduled time for job_b to start. I need some pattern to keep re-running job_b till job_a won't be returned by first NOT EXISTS
I did a test where job_a starts run one second before job_b. While job_b should be trying to restart as long as job_a disappears from system logs, it abandons the retries.
IF NOT EXISTS
(SELECT job.name FROM msdb.dbo.sysjobs_view job
INNER JOIN msdb.dbo.sysjobactivity activity ON job.job_id = activity.job_id
INNER JOIN msdb.dbo.syssessions sess ON sess.session_id = activity.session_id
INNER JOIN (SELECT MAX(agent_start_date) AS max_agent_start_date FROM msdb.dbo.syssessions) sess_max ON sess.agent_start_date = sess_max.max_agent_start_date
WHERE run_requested_date IS NOT NULL
AND stop_execution_date IS NULL
AND job.name = 'job_a')
BEGIN
DECLARE #path_diff varchar(max)
SET #path_diff = 'H:\MSSQL13.MSSQLSERVER\MSSQL\Backup\dev\db_name' + CONVERT(varchar, GETDATE(), 112) + REPLACE(CONVERT(varchar, GETDATE(), 114),':','') + '_DIFF_COMP.BAK'
BACKUP DATABASE [db_name] TO DISK = #path_diff WITH COMPRESSION, DIFFERENTIAL , STATS = 10
END
--need a step that will re-start the job once job_a doesn't appear in NOT EXISTS
ELSE
EXEC msdb.dbo.sp_stop_job N'job_b'
PRINT 'Full backup is taking longer then usual, please inspect!'
EXEC msdb.dbo.sp_start_job N'job_b'

How do I get the user who invoked a SQL Agent job?

I'm working on a job step which needs to reference the Login Name value for the user who started the job. It'll be passed as a value into a table field, which is then referenced by other processes.
I haven't been able to find if or where the starting username is stored in system tables. It must be stored somewhere as the (job outcome) step in msdb.dbo.sysjobhistory references is thusly:
The job succeeded. The Job was invoked by User [domain]\[username]. The last step to run was...
I'd like to capture that [domain]\[username] value for my job step. I know it can be done as a subsequent job, referencing the original and doing some string manipulation, but I'd prefer to do it in the same job, if possible.
Thanks in advance!
That is logged in the message column of the msdb.dbo.sysjobhistory table.
You may want to do some joins to the sysjobs table as well. I.E.
select
j.name as 'JobName',
run_date,
run_time,
msdb.dbo.agent_datetime(run_date, run_time) as 'RunDateTime',
case
when left(h.message,16) = 'Executed as user'
then substring(h.message,19,charindex('.',h.message,1) - 18)
when h.message like '%invoked by%'
then substring(h.message,charindex('invoked by ',h.message) + 11,charindex('.',substring(h.message,charindex('invoked by ',h.message) + 11,99)) - 1)
else h.message
end
From
msdb.dbo.sysjobs j
INNER JOIN
msdb.dbo.sysjobhistory h
ON j.job_id = h.job_id
where
j.enabled = 1 --Only Enabled Jobs
order by
JobName,
RunDateTime desc
REF

SQL Server 2012 job scheduling

I have a situation where I have 1 package (Package A) that take about 3 min to complete and another package (Package B) that takes about 4 min to complete. I need package A to run every 5 min via a job and package B to run every 15 min. However package B can only run after package A has been completed.
Example
5- Package A runs
10- Package A runs
15- Package A runs and then Package B
20- Package A runs
25- Package A runs
30- Package A runs and then Package B
Is there any way to schedule jobs to meet the requirements above?
Really appreciate your help. Thanks in advance!
for package B i would just put in logic to check if package A has stopped running
the wait script would be
WHILE EXISTS (
SELECT
*
FROM
msdb.dbo.sysjobs_view job
JOIN
msdb.dbo.sysjobactivity activity
ON
job.job_id = activity.job_id
JOIN
msdb.dbo.syssessions sess
ON
sess.session_id = activity.session_id
JOIN
(
SELECT
MAX( agent_start_date ) AS max_agent_start_date
FROM
msdb.dbo.syssessions
) sess_max
ON
sess.agent_start_date = sess_max.max_agent_start_date
WHERE
run_requested_date IS NOT NULL AND stop_execution_date IS NULL
AND job.name = 'package A')
BEGIN
WAITFOR DELAY '00:00:30';
END
This would check every 30 seconds if package A has stopped running.
Alternatively, you create a table that would keep track of job status and have A write to it to keep track of the status.

Whether SQL Blocking Session will be cleared by itself?

I can view the blocking session in our Production DB.
SELECT * FROM sys.sysprocesses WHERE spid = YOURSPID
I have not killed the session : Kill <SPID>
Does the blocking session will get clear by itself ?
It depends on the user(if any) who is active and who if any is executing the query. If there is any active user who has blocked the session then you have to kill the session for that user or else wait for him/his session to get finished. You can execute the sp_whoisactive to check the list of active users. And check if any user is blocking the session then you can explicitly kill the session for that user to get it working.
You can also refer: Identify the cause of SQL Server blocking.
This query is also a good way to analyze detailed information about
locks, and help you to identify the cause of a large number of blocks.
WITH [Blocking]
AS (SELECT w.[session_id]
,s.[original_login_name]
,s.[login_name]
,w.[wait_duration_ms]
,w.[wait_type]
,r.[status]
,r.[wait_resource]
,w.[resource_description]
,s.[program_name]
,w.[blocking_session_id]
,s.[host_name]
,r.[command]
,r.[percent_complete]
,r.[cpu_time]
,r.[total_elapsed_time]
,r.[reads]
,r.[writes]
,r.[logical_reads]
,r.[row_count]
,q.[text]
,q.[dbid]
,p.[query_plan]
,r.[plan_handle]
FROM [sys].[dm_os_waiting_tasks] w
INNER JOIN [sys].[dm_exec_sessions] s ON w.[session_id] = s.[session_id]
INNER JOIN [sys].[dm_exec_requests] r ON s.[session_id] = r.[session_id]
CROSS APPLY [sys].[dm_exec_sql_text](r.[plan_handle]) q
CROSS APPLY [sys].[dm_exec_query_plan](r.[plan_handle]) p
WHERE w.[session_id] > 50
AND w.[wait_type] NOT IN ('DBMIRROR_DBM_EVENT'
,'ASYNC_NETWORK_IO'))
SELECT b.[session_id] AS [WaitingSessionID]
,b.[blocking_session_id] AS [BlockingSessionID]
,b.[login_name] AS [WaitingUserSessionLogin]
,s1.[login_name] AS [BlockingUserSessionLogin]
,b.[original_login_name] AS [WaitingUserConnectionLogin]
,s1.[original_login_name] AS [BlockingSessionConnectionLogin]
,b.[wait_duration_ms] AS [WaitDuration]
,b.[wait_type] AS [WaitType]
,t.[request_mode] AS [WaitRequestMode]
,UPPER(b.[status]) AS [WaitingProcessStatus]
,UPPER(s1.[status]) AS [BlockingSessionStatus]
,b.[wait_resource] AS [WaitResource]
,t.[resource_type] AS [WaitResourceType]
,t.[resource_database_id] AS [WaitResourceDatabaseID]
,DB_NAME(t.[resource_database_id]) AS [WaitResourceDatabaseName]
,b.[resource_description] AS [WaitResourceDescription]
,b.[program_name] AS [WaitingSessionProgramName]
,s1.[program_name] AS [BlockingSessionProgramName]
,b.[host_name] AS [WaitingHost]
,s1.[host_name] AS [BlockingHost]
,b.[command] AS [WaitingCommandType]
,b.[text] AS [WaitingCommandText]
,b.[row_count] AS [WaitingCommandRowCount]
,b.[percent_complete] AS [WaitingCommandPercentComplete]
,b.[cpu_time] AS [WaitingCommandCPUTime]
,b.[total_elapsed_time] AS [WaitingCommandTotalElapsedTime]
,b.[reads] AS [WaitingCommandReads]
,b.[writes] AS [WaitingCommandWrites]
,b.[logical_reads] AS [WaitingCommandLogicalReads]
,b.[query_plan] AS [WaitingCommandQueryPlan]
,b.[plan_handle] AS [WaitingCommandPlanHandle]
FROM [Blocking] b
INNER JOIN [sys].[dm_exec_sessions] s1
ON b.[blocking_session_id] = s1.[session_id]
INNER JOIN [sys].[dm_tran_locks] t
ON t.[request_session_id] = b.[session_id]
WHERE t.[request_status] = 'WAIT'
GO

Long running job

I am not sure what is going on? I still get an email even though the job stopped running at 11:50 pm which clearly is less than thean 7 hours being that it started at 7 pm last night..It is suppose to email me if the job runs longer than 7 hours and for some reason yesterday it worked in test but today its not..Any ideas???
SELECT *
FROM msdb..sysjobactivity aj
JOIN msdb..sysjobs sj on sj.job_id = aj.job_id
WHERE DATEDIFF(HOUR,aj.start_execution_date,GetDate())> 7
AND aj.start_execution_date IS NOT NULL
AND sj.name = 'Nightly_Job'
and not exists ( -- make sure this is the most recent run
select 1
from msdb..sysjobactivity new
where new.job_id = aj.job_id
and new.start_execution_date > aj.start_execution_date)
if ##ROWCOUNT > 0
BEGIN
USE msdb
EXEC sp_send_dbmail
#profile_name = 'DB_Mail',
#recipients = 'xxx#yyy.com',
#subject = 'T-SQL Query Result',
#body = 'The Nightly_Job has been running 7
The problem with your query is that it only checks how long has passed since the job was started... it doesn't take into account when the job completed.
If there are no other executions of the job within 7 hours, then your check that limits the query to the most recent run doesn't exclude the previously completed job... your query then returns the job that was started over 7 hours ago, but in this case completed within 4 hours.
To fix your query to exclude completed jobs, modify your query as follows:
SELECT *
FROM
msdb..sysjobactivity aj
JOIN msdb..sysjobs sj on sj.job_id = aj.job_id
WHERE
DATEDIFF(HOUR, aj.start_execution_date,
ISNULL(aj.stop_execution_date, GetDate()) )> 7
AND sj.name = 'Nightly_Job'
AND NOT EXISTS ( -- make sure this is the most recent run
SELECT 1
FROM msdb..sysjobactivity new
WHERE new.job_id = aj.job_id
AND new.start_execution_date > aj.start_execution_date)