DOWNLOAD THE CODE:
Download the Code 45034.zip

The sp_who stored procedure is one of the most commonly used items in a SQL Server DBA's toolbox. Sp_who provides information about many crucial SQL Server user connections and processes such as login name, host name, database, command, and process ID. But sp_who displays results in a cumbersome format that contains excessive white space and forces users to waste time looking for the information that's important to them. Since SQL Server 7.0, a similar but undocumented stored procedure, sp_who2, has sneaked into the master database. Sp_who2 targets some of sp_who's weaknesses by removing certain columns, adding others, and displaying them in a more compact format. Thanks to these improvements, sp_who2 has gradually gained popularity. However, both sp_who and sp_who2 have a couple of serious drawbacks: They have limited filtering capabilities and they don't show blocks clearly. In an effort to streamline my own process analysis, I decided to write my own, modified version of sp_who.

Any DBA who works with sp_who and sp_who2 must work within the limitations of those stored procedures. First, the procedures provide only limited filtering. For example, sp_who lets you filter by login name, but sp_who2 doesn't. However, on large, busy SQL Servers, a DBA can't (and doesn't need to) look at all connections. Filtering out unwanted information lets DBAs quickly get the information they're interested in. Second, neither member of the sp_who family can show blocks clearly. A blocking chain usually includes one or more culprit server process IDs (SPIDs) that cause all subsequent blocks. (For information about detecting blocked processes, see Kalen Delaney's article "Track Down Troublemakers," August 2003, InstantDoc ID 39453 and the SQL Server Books Online—BOL—section "Understanding and Avoiding Blocking.") Detecting and fixing the blocked process at the head of the chain is essential to solving blocking-related database-performance problems. (For an explanation of how to solve blocking problems, see the Microsoft article "Resolving blocking problems that are caused by lock escalation in SQL Server" at http://support.microsoft.com/default.aspx?scid=kb;en-us;323630.)

Sp_who and sp_who2 also have other minor limitations. For instance, the parameter sp_who 'active' lists what BOL calls "active processes," which always include a dozen or so system processes such as Task Manager, Signal Handler, Log Writer, and Lazy Writer—processes that aren't necessarily important to daily administrative tasks but are vital to SQL Server, so DBAs can't leave them out of sp_who's results. Taking these SPIDs out of the list of runnable processes gives you a clearer look at what's going on in your databases. And I was surprised to find that sp_who2's loginame parameter doesn't filter results by login name, as its name implies. In fact, it doesn't filter anything. A close inspection of the code revealed that the login filtering part of the stored procedure is commented out. Well, quirks like this one are probably why sp_who2 is undocumented.

The stored procedure I wrote, sp_who1, is a modified version of sp_who and sp_who2 that works with SQL Server 2000 and 7.0 and has more input parameters to filter out unwanted information. In addition to inheriting the beneficial features of its predecessors, the new stored procedure provides a flexible way to investigate SQL Server connections by SPID, status, login, command, database, host, last batch, program, or any combination of these factors. Sp_who1 also helps troubleshoot performance by detecting waiting processes and potential blocking.

Introducing sp_who1
Web Listing 1 contains the complete sp_who1 stored procedure. When you download the listing at InstantDoc ID 45034, you'll notice that the code looks significantly different from the sp_who and sp_who2 code you're used to. Let's take a look at the features I included.

An impressive feature of sp_who1 is that it takes more than 10 input parameters for filtering. Table 1 shows summary descriptions of these parameters and how to use them. The parameter @spidpool has a variable capacity, allowing an average of 100 SPIDs, which is more than enough for a typical DBA's use. In my experience, if I need to check more than half a dozen SPIDs, I regard the task as more than spot-checking, and I can usually find a better filter to help me. For example, I might filter the SPIDs by the name of the database the SPIDs are connected to or by one user-machine name (hostname) where the SPIDs originate. Also, note that the variables @waittime and @blocked have different meanings when you supply them with a 0 value. When you use @waittime = 0, you see all the waiting processes, whereas @blocked = 0 lists all the nonblocked processes.

Table 2 compares the three members of the sp_who family. Without input parameters, all of these stored procedures will query the master.dbo.sysprocesses table with no filtering or sorting. When you want to sort with sp_who and sp_who2, you're limited to sorting by SPID. But I think sorting on columns other than the spid column makes more sense because a SPID is less meaningful than other identifiers such as database name or login name. I wrote sp_who1 so that it sorts results by database, login name, status, and command—an order that covers most of my routine needs. I decided to filter out system background processes because I believe few DBAs are really interested in them. I used @status = runnable to paint a cleaner picture of processes that are more important than the active value that sp_who and sp_who2 use. And filtering a pool of selected SPIDs that all users are interested in eliminates the need to run the stored procedure repeatedly. Sp_who and sp_who2 have to run once for every SPID. So, if you have five SPIDs, the stored procedure has to run five times. With sp_who1, you need to run the stored procedure only once, and you get the same results as you would with sp_who's and sp_who2's five separate runs. And sp_who1 displays the SPIDs you're most interested in on one screen.

The power of filters increases when you combine them, so I made sure sp_who1 had this capability. I call this feature multiple filter panning, and you'll love the "gold" that the panning turns up. You can vary the combinations of filters you use, depending on your situation. For example, some users run programs that connect to multiple databases. I can use @loginame and @dbname together to filter user connections by login name, then further filter by specifying the database that has a problem. Sometimes I use @status, @command, and @program together to find out which users are using our Asset Inventory application to perform inserts. Using combined filters like this gives you the advantage of convenience and efficiency. With the right combination of filters, a DBA can find a specific SPID in a second instead of wasting time searching for a needle in a haystack.

   Prev. page   [1] 2 3     next page



You must log on before posting a comment.

If you don't have a username & password, please register now.

Reader Comments

Good article. Will definitely use this proc

srini_kris

Article Rating 5 out of 5

Very good overall. The only disappointment was that, when I run it at least, I don't get formatted output in TEXT mode like your example shows - mine's all strung together so that the columns don't line up with the headers. I can run it in GRID mode, but then I lose the output messages (like "Head(s) of blocking chain is(are):" )

pyale

Article Rating 4 out of 5

Example of the above:

SPID,status,loginame,dbname,command,hostname,memusg,phys_io,login_time,last_batch,SPID,program,cpu,opentran,blkBy,waittime,lastwaittype,waitresource,SPID 56,sleeping ,REACH\philip.yale,master,DELETE ,REA0491L-IBM,8,4,02/28/2005 17:14:42,02/28/2005 17:14:42,56,SQL Query Analyzer ,30,2,55,938159,LCK_M_U,KEY: 9:405576483:1 (ed0175ce1a7b),56 57,sleeping ,REACH\philip.yale,master,SELECT ,REA0491L-IBM,5,0,02/28/2005 17:14:42,02/28/2005 17:14:42,57,SQL Query Analyzer ,631,0,55,910820,LCK_M_S,KEY: 9:405576483:2 (c000178c23b1),57 55,sleeping ,REACH\philip.yale,master,UPDATE ,REA0491L-IBM,14,16,02/28/2005 17:14:41,02/28/2005 17:19:40,55,SQL Query Analyzer ,831,2,53,960241,LCK_M_U,KEY: 9:1977058079:1 (100198c3f985),55

pyale

Article Rating 4 out of 5

Hmm. The example above is far worse than reality - ignore the example, the web formatting's has made it even worse.

pyale

Article Rating 4 out of 5

Very useful. FYI: The web code download wraps two long comment lines leading to parse errors but these are easily solved by re-joining the long lines. Richard: I thank you very much for creating/sharing this code. Very useful!

flexdba

Article Rating 5 out of 5

Excellent article. Thanks for your brains and hard work.

PatrickCurry

Article Rating 5 out of 5

Very Nice!

If you like sp_who1, you should try sp_who_3:

http://www.sqlservercentral.com/scripts/contributions/1232.asp

It got like a perfect 5 stars and seems to be more efficient, more powerful, and has even more filtering and even include ad-hoc sorting. Check it out and post back comments.

This type of procedure has been desperately needed. I think Microsoft should release something like this in a service pack or in SQL 2005. There are plenty of sp_who_x out there on the web for free download.

Microsoft should just pick the best one and include it.

capone

Article Rating 5 out of 5

sp_who1 @loginame = [domain\username] won't work if the user is accessing via an NT group. Comment out the below and all is OK: if (@loginame is not null) begin if not exists (select 1 from master.dbo.syslogins with (nolock) where name = @loginame) begin raiserror(15007, -1, -1, @loginame) return (1) end end

Highway

Article Rating 4 out of 5

I downloaded this some time ago & found it to be a very useful tool. I created a file with various statments using sp_who1 as suggested. This has become an important part of my toolbox of utilities. Thanks!

howardr

Article Rating 5 out of 5

 
 

ADS BY GOOGLE