A Better sp_who2 using DMVs (sp_who3)
-
Posted on June 19, 2009 by Derek Dieter
-
3
The following code generates the same information found in sp_who2, along with some additional troubleshooting information. It also contains the SQL Statement being run, so instead of having to execute a separate DBCC INPUTBUFFER, the statement being executed is shown in the results.
Unlike sp_who2, this custom sp_who3 only shows sessions that have a current executing request.
What is also shown is the reads and writes for the current command, along with the number of reads and writes for the entire SPID. It also shows the protocol being used (TCP, NamedPipes, or Shared Memory).
The lead blocker below will show in the BlkBy column as -1.
AS
BEGIN
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
SELECT
SPID = er.session_id
,BlkBy = CASE WHEN lead_blocker = 1 THEN -1 ELSE er.blocking_session_id END
,ElapsedMS = er.total_elapsed_time
,CPU = er.cpu_time
,IOReads = er.logical_reads + er.reads
,IOWrites = er.writes
,Executions = ec.execution_count
,CommandType = er.command
,LastWaitType = er.last_wait_type
,ObjectName = OBJECT_SCHEMA_NAME(qt.objectid,dbid) + '.' + OBJECT_NAME(qt.objectid, qt.dbid)
,SQLStatement =
SUBSTRING
(
qt.text,
er.statement_start_offset/2,
(CASE WHEN er.statement_end_offset = -1
THEN LEN(CONVERT(nvarchar(MAX), qt.text)) * 2
ELSE er.statement_end_offset
END - er.statement_start_offset)/2
)
,STATUS = ses.STATUS
,[Login] = ses.login_name
,Host = ses.host_name
,DBName = DB_Name(er.database_id)
,StartTime = er.start_time
,Protocol = con.net_transport
,transaction_isolation =
CASE ses.transaction_isolation_level
WHEN 0 THEN 'Unspecified'
WHEN 1 THEN 'Read Uncommitted'
WHEN 2 THEN 'Read Committed'
WHEN 3 THEN 'Repeatable'
WHEN 4 THEN 'Serializable'
WHEN 5 THEN 'Snapshot'
END
,ConnectionWrites = con.num_writes
,ConnectionReads = con.num_reads
,ClientAddress = con.client_net_address
,Authentication = con.auth_scheme
,DatetimeSnapshot = GETDATE()
FROM sys.dm_exec_requests er
LEFT JOIN sys.dm_exec_sessions ses
ON ses.session_id = er.session_id
LEFT JOIN sys.dm_exec_connections con
ON con.session_id = ses.session_id
CROSS APPLY sys.dm_exec_sql_text(er.sql_handle) AS qt
OUTER APPLY
(
SELECT execution_count = MAX(cp.usecounts)
FROM sys.dm_exec_cached_plans cp
WHERE cp.plan_handle = er.plan_handle
) ec
OUTER APPLY
(
SELECT
lead_blocker = 1
FROM master.dbo.sysprocesses sp
WHERE sp.spid IN (SELECT blocked FROM master.dbo.sysprocesses)
AND sp.blocked = 0
AND sp.spid = er.session_id
) lb
ORDER BY
er.blocking_session_id DESC,
er.logical_reads + er.reads DESC,
er.session_id
END
- Comments (RSS)
- Trackback
- Permalink
This is awesome. i made one small change that others may find useful. Preceding the order by statement, I added the following where clause line to filter out the spwo3 process. change the name of the process, dbo.sp_who3 in this case, to whatever yours shows up as. This varies depending on where you placed the stored procedure.
where qt.objectid OBJECT_ID(‘dbo.sp_who3′)
ORDER BY
er.blocking_session_id DESC,
er.logical_reads + er.reads DESC,
er.session_id
END
This worked like a Charm Derek.. I was able to pinpoint the offender really quick and nip it in the bud.
Nice work but it only seems to find connections to the master,tempdb databases…
EXEC SP_WHO2 gives me about 100 result and your query only 20…
Hi Peter,
This is because this script only shows active connections. Personally I prefer this because when troubleshooting, I can immediately see how busy the server is just by the sheer number of results. sp_who2 will show all connections and I need to figure out which ones are asleep. To change this to show sleeping connections, simply join the sessions table first, then left join on the dm_exec_requests
Derek
Nice. I have a long running Select (over 50 minutes). I’m running sp_who3 with sp_who2 in the same window. who2 DiskIO column is increasing each time I rerun, but who3 IOReads and IOWrites are static at the same values as the first time I ran it in this SSMS window. I would have expected who3 to change. I can see who3 changing ElapsedMS. CPUTime looks frozen too. Is this behaving as intended? Thanks for the tool!
Excellent example, this is a big help for me in our monitoring application.
[...] fix. It is likely you have a run away query. The first thing you want to do is run sp_who2 (or sp_who3) and look for connections that have a SPID > 50 with abnormally high CPU time. The CPU time shown [...]





