List the queries running on SQL Server - sql-server

Is there a way to list the queries that are currently running on MS SQL Server (either through the Enterprise Manager or SQL) and/or who's connected?
I think I've got a very long running query is being execute on one of my database servers and I'd like to track it down and stop it (or the person who keeps starting it).

This will show you the longest running SPIDs on a SQL 2000 or SQL 2005 server:
select
P.spid
, right(convert(varchar,
dateadd(ms, datediff(ms, P.last_batch, getdate()), '1900-01-01'),
121), 12) as 'batch_duration'
, P.program_name
, P.hostname
, P.loginame
from master.dbo.sysprocesses P
where P.spid > 50
and P.status not in ('background', 'sleeping')
and P.cmd not in ('AWAITING COMMAND'
,'MIRROR HANDLER'
,'LAZY WRITER'
,'CHECKPOINT SLEEP'
,'RA MANAGER')
order by batch_duration desc
If you need to see the SQL running for a given spid from the results, use something like this:
declare
#spid int
, #stmt_start int
, #stmt_end int
, #sql_handle binary(20)
set #spid = XXX -- Fill this in
select top 1
#sql_handle = sql_handle
, #stmt_start = case stmt_start when 0 then 0 else stmt_start / 2 end
, #stmt_end = case stmt_end when -1 then -1 else stmt_end / 2 end
from sys.sysprocesses
where spid = #spid
order by ecid
SELECT
SUBSTRING( text,
COALESCE(NULLIF(#stmt_start, 0), 1),
CASE #stmt_end
WHEN -1
THEN DATALENGTH(text)
ELSE
(#stmt_end - #stmt_start)
END
)
FROM ::fn_get_sql(#sql_handle)

If you're running SQL Server 2005 or 2008, you could use the DMV's to find this...
SELECT *
FROM sys.dm_exec_requests
CROSS APPLY sys.dm_exec_sql_text(sql_handle)
More about sys.dm_exec_requests
More about sys.dm_exec_sql_text

You can run the sp_who command to get a list of all the current users, sessions and processes. You can then run the KILL command on any spid that is blocking others.

I would suggest querying the sys views. something similar to
SELECT *
FROM
sys.dm_exec_sessions s
LEFT JOIN sys.dm_exec_connections c
ON s.session_id = c.session_id
LEFT JOIN sys.dm_db_task_space_usage tsu
ON tsu.session_id = s.session_id
LEFT JOIN sys.dm_os_tasks t
ON t.session_id = tsu.session_id
AND t.request_id = tsu.request_id
LEFT JOIN sys.dm_exec_requests r
ON r.session_id = tsu.session_id
AND r.request_id = tsu.request_id
OUTER APPLY sys.dm_exec_sql_text(r.sql_handle) TSQL
This way you can get a TotalPagesAllocated which can help you figure out the spid that is taking all the server resources. There has lots of times when I can't even bring up activity monitor and use these sys views to see what's going on.
I would recommend you reading the following article. I got this reference from here.

As a note, the SQL Server Activity Monitor for SQL Server 2008 can be found by right clicking your current server and going to "Activity Monitor" in the context menu. I found this was easiest way to kill processes if you are using the SQL Server Management Studio.

There are various management views built into the product. On SQL 2000 you'd use sysprocesses. On SQL 2K5 there are more views like sys.dm_exec_connections, sys.dm_exec_sessions and sys.dm_exec_requests.
There are also procedures like sp_who that leverage these views. In 2K5 Management Studio you also get Activity Monitor.
And last but not least there are community contributed scripts like the Who Is Active by Adam Machanic.

SELECT
p.spid, p.status, p.hostname, p.loginame, p.cpu, r.start_time, r.command,
p.program_name, text
FROM
sys.dm_exec_requests AS r,
master.dbo.sysprocesses AS p
CROSS APPLY sys.dm_exec_sql_text(p.sql_handle)
WHERE
p.status NOT IN ('sleeping', 'background')
AND r.session_id = p.spid

Actually, running EXEC sp_who2 in Query Analyzer / Management Studio gives more info than sp_who.
Beyond that you could set up SQL Profiler to watch all of the in and out traffic to the server. Profiler also let you narrow down exactly what you are watching for.
For SQL Server 2008:
START - All Programs - Microsoft SQL Server 2008 - Performance Tools - SQL Server Profiler
Keep in mind that the profiler is truly a logging and watching app. It will continue to log and watch as long as it is running. It could fill up text files or databases or hard drives, so be careful what you have it watch and for how long.

In the Object Explorer, drill-down to: Server -> Management -> Activity Monitor. This will allow you to see all connections on to the current server.

You can use below query to find running last request:
SELECT
der.session_id
,est.TEXT AS QueryText
,der.status
,der.blocking_session_id
,der.cpu_time
,der.total_elapsed_time
FROM sys.dm_exec_requests AS der
CROSS APPLY sys.dm_exec_sql_text(sql_handle) AS est
Using below script you can also find number of connection per database:
SELECT
DB_NAME(DBID) AS DataBaseName
,COUNT(DBID) AS NumberOfConnections
,LogiName
FROM sys.sysprocesses
WHERE DBID > 0
GROUP BY DBID, LogiName
For more details please visit:
http://www.dbrnd.com/2015/06/script-to-find-running-process-session-logged-user-in-sql-server/

here is a query that will show any queries that are blocking. I am not entirely sure if it will just show slow queries:
SELECT p.spid
,convert(char(12), d.name) db_name
, program_name
, convert(char(12), l.name) login_name
, convert(char(12), hostname) hostname
, cmd
, p.status
, p.blocked
, login_time
, last_batch
, p.spid
FROM master..sysprocesses p
JOIN master..sysdatabases d ON p.dbid = d.dbid
JOIN master..syslogins l ON p.sid = l.sid
WHERE p.blocked = 0
AND EXISTS ( SELECT 1
FROM master..sysprocesses p2
WHERE p2.blocked = p.spid )

The right script would be like this:
select
p.spid, p.status,p.hostname,p.loginame,p.cpu,r.start_time, t.text
from sys.dm_exec_requests as r, sys.sysprocesses p
cross apply sys.dm_exec_sql_text(p.sql_handle) t
where p.status not in ('sleeping', 'background')
and r.session_id=p.spid

SELECT
p.spid, p.status, p.hostname, p.loginame, p.cpu, r.start_time, t.text
FROM
sys.dm_exec_requests as r,
master.dbo.sysprocesses as p
CROSS APPLY sys.dm_exec_sql_text(p.sql_handle) t
WHERE
p.status NOT IN ('sleeping', 'background')
AND r.session_id = p.spid
And
KILL #spid

in 2005 you can right click on a database, go to reports and there's a whole list of reports on transitions and locks etc...

Trying to put things together (hope to be helpful):
SELECT
p.spid,
RIGHT(CONVERT(varchar, DATEADD(ms, DATEDIFF(ms, p.last_batch, GETDATE()), '1900-01-01'), 121), 12) AS [batch_duration],
p.[program_name],
p.hostname,
MAX(p.loginame) AS loginame,
(SELECT SUBSTRING(text, COALESCE(NULLIF(spid.stmt_start, 0), 1) + 1, CASE spid.stmt_end WHEN -1 THEN DATALENGTH(text) ELSE (spid.stmt_end - spid.stmt_start) END) FROM ::fn_get_sql(spid.[sql_handle])) AS [sql]
FROM
master.dbo.sysprocesses p
LEFT JOIN (
SELECT
ROW_NUMBER() OVER(PARTITION BY spid ORDER BY ecid) AS i,
spid,
[sql_handle],
CASE stmt_start WHEN 0 THEN 0 ELSE stmt_start / 2 END AS stmt_start,
CASE stmt_end WHEN -1 THEN -1 ELSE stmt_end / 2 END AS stmt_end
FROM sys.sysprocesses
) spid ON p.spid = spid.spid AND spid.i = 1
WHERE
p.spid > 50
AND p.status NOT IN ('background', 'sleeping')
AND p.cmd NOT IN ('AWAITING COMMAND', 'MIRROR HANDLER', 'LAZY WRITER', 'CHECKPOINT SLEEP', 'RA MANAGER')
GROUP BY
p.spid,
p.last_batch,
p.[program_name],
p.hostname,
spid.stmt_start,
spid.stmt_end,
spid.[sql_handle]
ORDER BY
batch_duration DESC,
p.spid
;

Use Sql Server Profiler (tools menu) to monitor executing queries and use activity monitor in Management studio to see how is connected and if their connection is blocking other connections.

You should try very usefull procedure sp_whoIsActive which can be found here: http://whoisactive.com and it is free.

Related

Who (Or What) ran this query ID

I'd like to know who (Service account, user account ,etc ) ran each query_id that Query_Store records. Is there a way to do this? I've looked all over and can't seem to find anything.
Basically I'd like the data from this to be stored as well. Hostname, and Login Name are very useful to me.
SELECT sdest.DatabaseName
,sdes.session_id
,sdes.[host_name]
,sdes.[program_name]
,sdes.client_interface_name
,sdes.login_name
,sdes.login_time
,sdes.nt_domain
,sdes.nt_user_name
,sdec.client_net_address
,sdec.local_net_address
,sdest.ObjName
,sdest.Query
FROM sys.dm_exec_sessions AS sdes
INNER JOIN sys.dm_exec_connections AS sdec ON sdec.session_id = sdes.session_id
CROSS APPLY (
SELECT db_name(dbid) AS DatabaseName
,object_id(objectid) AS ObjName
,ISNULL((
SELECT TEXT AS [processing-instruction(definition)]
FROM sys.dm_exec_sql_text(sdec.most_recent_sql_handle)
FOR XML PATH('')
,TYPE
), '') AS Query
FROM sys.dm_exec_sql_text(sdec.most_recent_sql_handle)
) sdest
where sdes.session_id <> ##SPID
--and sdes.nt_user_name = '' -- Put the username here !
ORDER BY sdec.session_id
Credit: Execution datetime for SQL queries against SQL Server
There's no DMV that records which sessions ran which queries. To gather that information you must use an Extended Events trace, or a Database Audit.

SQL Server service takes more memory and how to find which user session/process is taking more memory?

SQL Server service in my environment takes more memory and I need to find which process takes more memory and wants to kill it. We tried to find using the below query but the value in SQL server service and value returned from the query is not matching.
SELECT spid,
RTRIM(status) AS Status,
SUSER_SNAME(sid) AS [User],
RTRIM(hostname) AS Host,
RTRIM(program_name) AS Program,
memusage * 8 AS memusage,
cpu,
physical_io,
blocked,
CASE WHEN sysprocesses.dbid = 0 THEN '-' ELSE DB_NAME(sysprocesses.dbid)END AS [Database],
cmd,
last_batch,
login_time,
net_library,
loginame,
h.text,
waittime,
lastwaittype,
waitresource
FROM master..sysprocesses
LEFT OUTER JOIN sys.dm_exec_connections dmexec ON dmexec.session_id = spid
OUTER APPLY sys.dm_exec_sql_text(dmexec.most_recent_sql_handle) h
WHERE hostname != '';

Joins and linked servers query causing delay

Hey guys the code below is taking a really long time. I've been looking at it for quite a while. Is there anything that stands out as the obvious cause of delay?
[SQLSRV-3-JB] is a linked server BTW
Select count(cast (Unique_ID as bigint)) as [Count],
T.[Region_Code],
T.[Region_Name],
U.[Region_Code],
Y.[Examination_Year],
case when [Subject] = 'MUSIC THEORY' THEN 'Theory'
else 'Practical'
end
from [SQLSRV-3-JB].[X].[dbo].[Exam_and_Candidate_Details] Y
left join [SQLSRV-3-JB].[X].[dbo].[UK_Exam_Centre_Info] T
on Y.Centre_Code = T.Centre_Code
left join [SQLSRV-3-JB].[X].[dbo].[UK_Exam_Centres] U
on Y.Centre_Code = U.Centre_Code
where Y.[Examination_Year] between 2010 and 2016
group by Y.[Examination_Year],
T.[Region_Code],
T.[Region_Name],
U.[Region_Code],
case when [Subject] = 'MUSIC THEORY' THEN 'Theory'
else 'Practical'
end
Yes, there is one very obvious problem - the remote server. When you use a linked server like this, SQL Server has a disturbing habit of pulling all of the data in the remote tables to the local server before performing JOINs or filtration.
The correct way to handle this is to make this query a view on the remote server, and query the view with your WHERE clause on your end. So, your remote code would look like this:
-- Remote Server
USE X
GO
CREATE VIEW dbo.ExamCenterInfo
AS
Select count(cast (Unique_ID as bigint)) as [Count],
T.[Region_Code],
T.[Region_Name],
U.[Region_Code],
Y.[Examination_Year],
case when [Subject] = 'MUSIC THEORY' THEN 'Theory'
else 'Practical'
end
from dbo.[Exam_and_Candidate_Details] Y
left join dbo.[UK_Exam_Centre_Info] T
on Y.Centre_Code = T.Centre_Code
left join dbo.[UK_Exam_Centres] U
on Y.Centre_Code = U.Centre_Code
group by Y.[Examination_Year],
T.[Region_Code],
T.[Region_Name],
U.[Region_Code],
case when [Subject] = 'MUSIC THEORY' THEN 'Theory'
else 'Practical'
end
Then your local code:
-- Local Server
SELECT *
FROM [SQLSRV-3-JB].[X].[dbo].ExamCenterInfo ECI
where ECI.[Examination_Year] between 2010 and 2016
NOTE: There is some possibility that this will pull all of the view output before filtering by year. If this is still a problem, you will have to create a more complex mechanism to execute the view with filtration on the remote server.

How to get sysprocesses.program_name for current connection

I need to retrieve the value of sysprocesses.program_name for the current connection. I use Sql Server 2008R2.
In other words i would like to join sysprocesses to this
select * from sys.dm_exec_connections
where session_id = ##SPID
But i am not succeeding.
Just to explain the context:
I need to know program_name of the current session because the application i am working on writes info about who is logged in into the system (it does not depend on sql serveer user, because sa is used for connection) into program_name (it is a trick).
If I could read program_name i would be able to implement some custom logic into a INSTEAD OF UPDATE trigger i am writing.
i am twaking a legacy application by working on triggers only (it is "emergency maintenance").
Use this builtin function:
select app_name()
Alternatively, you can use this query to get more than only the name of the program:
select *
from sys.[dm_exec_connections] as [dec]
inner join [sys].[sysprocesses] as [sp] on [dec].[session_id] = [sp].[spid]
where [dec].[session_id] = ##SPID
Ant_22: yes you can see Application Name if you add "Application Name" in connection string, exemple to see how many connections per process:
SELECT
DB_NAME(dbid) as DBName,
COUNT(dbid) as NumberOfConnections,
PROGRAM_NAME as ProgName,
loginame as LoginName
FROM
sys.sysprocesses
WHERE
dbid > 0
GROUP BY
dbid, PROGRAM_NAME, loginame

Automatically stop SQL Server Agent when no jobs are running [duplicate]

I have around 40 different sql server jobs in one instance. They all have different schedules. Some run once a day some every two mins some every five mins. If I have a need to stop sql server agent, how can I find the best time when no jobs are running so I won't interrupt any of my jobs?
how can I find the best time when no jobs are running so I won't interrupt any of my jobs?
You basically want to find a good window to perform some maintenance. #MaxVernon has blogged about it here with a handy script
/*
Shows gaps between agent jobs
-- http://www.sqlserver.science/tools/gaps-between-sql-server-agent-jobs/
-- requires SQL Server 2012+ since it uses the LAG aggregate.
Note: On SQL Server 2005, SQL Server 2008, and SQL Server 2008 R2, you could replace the LastEndDateTime column definition with:
LastEndDateTime = (SELECT TOP(1) s1a.EndDateTime FROM s1 s1a WHERE s1a.rn = s1.rn - 1)
*/
DECLARE #EarliestStartDate DATETIME;
DECLARE #LatestStopDate DATETIME;
SET #EarliestStartDate = DATEADD(DAY, -1, GETDATE());
SET #LatestStopDate = GETDATE();
;WITH s AS
(
SELECT StartDateTime = msdb.dbo.agent_datetime(sjh.run_date, sjh.run_time)
, MaxDuration = MAX(sjh.run_duration)
FROM msdb.dbo.sysjobs sj
INNER JOIN msdb.dbo.sysjobhistory sjh ON sj.job_id = sjh.job_id
WHERE sjh.step_id = 0
AND msdb.dbo.agent_datetime(sjh.run_date, sjh.run_time) >= #EarliestStartDate
AND msdb.dbo.agent_datetime(sjh.run_date, sjh.run_time) < = #LatestStopDate
GROUP BY msdb.dbo.agent_datetime(sjh.run_date, sjh.run_time)
UNION ALL
SELECT StartDate = DATEADD(SECOND, -1, #EarliestStartDate)
, MaxDuration = 1
UNION ALL
SELECT StartDate = #LatestStopDate
, MaxDuration = 1
)
, s1 AS
(
SELECT s.StartDateTime
, EndDateTime = DATEADD(SECOND, s.MaxDuration - ((s.MaxDuration / 100) * 100)
+ (((s.MaxDuration - ((s.MaxDuration / 10000) * 10000))
- (s.MaxDuration - ((s.MaxDuration / 100) * 100))) / 100) * 60
+ (((s.MaxDuration - ((s.MaxDuration / 1000000) * 1000000))
- (s.MaxDuration - ((s.MaxDuration / 10000) * 10000))) / 10000) * 3600, s.StartDateTime)
FROM s
)
, s2 AS
(
SELECT s1.StartDateTime
, s1.EndDateTime
, LastEndDateTime = LAG(s1.EndDateTime) OVER (ORDER BY s1.StartDateTime)
FROM s1
)
SELECT GapStart = CONVERT(DATETIME2(0), s2.LastEndDateTime)
, GapEnd = CONVERT(DATETIME2(0), s2.StartDateTime)
, GapLength = CONVERT(TIME(0), DATEADD(SECOND, DATEDIFF(SECOND, s2.LastEndDateTime, s2.StartDateTime), 0))
FROM s2
WHERE s2.StartDateTime > s2.LastEndDateTime
ORDER BY s2.StartDateTime;
The question title scared me a bit - I thought you wanted to programmatically shut the SQL Server agent down anytime there were no jobs running. My answer to that question would be "Why?" There is no need to.
But if you are just looking to do a planned restart or shut down and you don't have a third party tool like Sentry One's SQL Sentry Event Manager to have a visualization, I would just let the SQL Server Agent Job History and Job Activity Monitor help here. The Job Activity monitor can show you which jobs are running right now in the status column. You can also see the last execute and next execute dates and times.
In the object browser in SSMS, connect to your instance, then expand SQL Server Agent, then you'll see Jobs and under that you'll see "Job Activity Monitor" - this view should show you what you need.
Also - don't worry about shutting down before a job executes. If you do that, you will either have that job just missing its schedule and you can let it run when it is next due to (depending on the job and its purpose) or you can manually right click and execute the job.
For more on the activity monitor for jobs, see Monitor Job Activity in the product documentation.
I recommend creating a script that will disable your jobs. Disabled jobs still exist but will not be automatically launched by their schedules. Run this script (based on procedure sp_update_job in the msdb database) to disable jobs, wait for any currently running jobs to finish execution, then stop SQL agent. A similar script to re-enable disabled jobs would be useful. You might need to plan around jobs that are and should remain disabled.
A complete “SQL Agent shutdown” process could be fully scripted, but I question the wisdom of doing so. A bit of research implies that there is no 100% reliable way of programmatically telling if a given job is or is not running, and while there is an undocumented (where "undocumented" means "you really shouldn't be using this") system procedure for stopping and starting services, doing so from with SQL Server itself seems like a pretty bad idea.
You can query the system tables as shown by Dattatrey Sindol in the MSSQLTips.com article Querying SQL Server Agent Job Information:
SELECT
[sJOB].[job_id] AS [JobID]
, [sJOB].[name] AS [JobName]
, [sDBP].[name] AS [JobOwner]
, [sCAT].[name] AS [JobCategory]
, [sJOB].[description] AS [JobDescription]
, CASE [sJOB].[enabled]
WHEN 1 THEN 'Yes'
WHEN 0 THEN 'No'
END AS [IsEnabled]
, [sJOB].[date_created] AS [JobCreatedOn]
, [sJOB].[date_modified] AS [JobLastModifiedOn]
, [sSVR].[name] AS [OriginatingServerName]
, [sJSTP].[step_id] AS [JobStartStepNo]
, [sJSTP].[step_name] AS [JobStartStepName]
, CASE
WHEN [sSCH].[schedule_uid] IS NULL THEN 'No'
ELSE 'Yes'
END AS [IsScheduled]
, [sSCH].[schedule_uid] AS [JobScheduleID]
, [sSCH].[name] AS [JobScheduleName]
, CASE [sJOB].[delete_level]
WHEN 0 THEN 'Never'
WHEN 1 THEN 'On Success'
WHEN 2 THEN 'On Failure'
WHEN 3 THEN 'On Completion'
END AS [JobDeletionCriterion]
FROM
[msdb].[dbo].[sysjobs] AS [sJOB]
LEFT JOIN [msdb].[sys].[servers] AS [sSVR]
ON [sJOB].[originating_server_id] = [sSVR].[server_id]
LEFT JOIN [msdb].[dbo].[syscategories] AS [sCAT]
ON [sJOB].[category_id] = [sCAT].[category_id]
LEFT JOIN [msdb].[dbo].[sysjobsteps] AS [sJSTP]
ON [sJOB].[job_id] = [sJSTP].[job_id]
AND [sJOB].[start_step_id] = [sJSTP].[step_id]
LEFT JOIN [msdb].[sys].[database_principals] AS [sDBP]
ON [sJOB].[owner_sid] = [sDBP].[sid]
LEFT JOIN [msdb].[dbo].[sysjobschedules] AS [sJOBSCH]
ON [sJOB].[job_id] = [sJOBSCH].[job_id]
LEFT JOIN [msdb].[dbo].[sysschedules] AS [sSCH]
ON [sJOBSCH].[schedule_id] = [sSCH].[schedule_id]
ORDER BY [JobName]

Resources