{"id":242,"date":"2007-03-22T00:00:00","date_gmt":"2007-03-22T00:00:00","guid":{"rendered":"https:\/\/test.simple-talk.com\/uncategorized\/pop-rivett-and-the-case-of-the-rogue-spids\/"},"modified":"2021-09-29T16:22:21","modified_gmt":"2021-09-29T16:22:21","slug":"pop-rivett-and-the-case-of-the-rogue-spids","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/databases\/sql-server\/t-sql-programming-sql-server\/pop-rivett-and-the-case-of-the-rogue-spids\/","title":{"rendered":"Pop Rivett and the Case of the Rogue SPIDs"},"content":{"rendered":"<p><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/368-Image1.gif\" alt=\"368-Image1.gif\" \/><\/p>\n<p><em>My dear fellow, you know my methods&#8230;<\/em><\/p>\n<p>Pop Rivett put down his violin, stretched back in his fireside chair, and stared severely at me. &#8220;My dear fellow, you know my methods. The mystery of the rogue SPIDs has been one of the more exacting tasks it has been my fortune to be given.<\/p>\n<p>A process in a complex database occasionally, and apparently randomly, manages to put table locks on vital tables. The result? Several applications are brought to a complete halt. Tracking down the problem was indeed taxing, but through the faculties of deduction and of logical synthesis which I have endeavoured to apply to the task, I consider that I helped the DBA, Lestrade, with some small points in connection with it.&#8221;<\/p>\n<p>I smiled ruefully, and shook my head. &#8220;I was relying on traces and found myself completely inundated and overwhelmed by the detail. I doubt I ever would have solved the mystery!&#8221;<\/p>\n<p>&#8220;Not so, you are too modest. However, I allow that a certain selection and discretion is necessary for producing a rapid result&#8221;.<\/p>\n<p>Rivett strummed a few notes on his violin before continuing. &#8220;In solving the mysteries of the performance of a database application, one often needs to view a list of the processes currently running on your server; how long each process has been running, what the command was, what is blocking, and how much I\/O it is causing.&#8221;<\/p>\n<p>&#8220;How in the name of good fortune would you know all that, Rivett?&#8221;<\/p>\n<p>&#8220;Elementary, dear fellow. All you need is a stored procedure that will report any SPIDs that are blocking others, the last command executed, and other useful diagnostic attributes. You then need to run it every minute or so on the SQL Server agent, inserting the results into a log table which has a &#8216;timestamp&#8217; column, until you catch the process &#8216;in flagrante delicto&#8217;. You will then be able to see the command that is doing the blocking, and the processes being blocked.&#8221;<\/p>\n<p>&#8220;Surely, Rivett!&#8221; I interjected, &#8220;<b>sp_who<\/b> and <b>sp_who2<\/b> will show you the basic details of the processes, and the SPID is just the primary key of the <b>sysprocesses<\/b> table&#8221;<\/p>\n<p>Rivett looked at me pityingly. &#8220;Quite! But they will show you all the processes running, not just the blocking processes. Furthermore, they will not tell you what was being executed will they? Try out my <b>sp_SpidByStatus <\/b>procedure. It requires little skill.<\/p>\n<p>You&#8217;ll want to call the procedure with a &#8216;blk&#8217; parameter to reveal all blocked and blocking spids. The default status is &#8216;runnable&#8217; as that is the usual requirement, but you can call the procedure with &#8216;all&#8217; as a parameter, so that all SPIDs are displayed. If you call the procedure with a SPID, then just that SPID is displayed.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/368-Image2.gif\" alt=\"368-Image2.gif\" \/><\/p>\n<p><em>Examining the sp_SpidByStatus procedure<\/em><\/p>\n<p>Take a look at the procedure. I&#8217;d show you it on my laptop except the damned battery is flat! Note form will have to suffice&#8230;<\/p>\n<pre><\/pre>\n<p class=\"MsoNormal\">if exists (select * from sysobjects where id = object_id(N'[dbo].[sp_SpidByStatus]&#8217;)<br \/> \t\t\t\t        and OBJECTPROPERTY(id, N&#8217;IsProcedure&#8217;) = 1)<\/p>\n<p class=\"MsoNormal\">drop procedure [dbo].[sp_SpidByStatus]<\/p>\n<p class=\"MsoNormal\">GO<\/p>\n<p class=\"MsoNormal\">\n<p class=\"MsoNormal\">Create procedure [dbo].[sp_SpidByStatus]<\/p>\n<p class=\"MsoNormal\">@status varchar(20) = &#8216;runnable&#8217;<\/p>\n<p class=\"MsoNormal\">as<\/p>\n<p class=\"MsoNormal\">\/*<\/p>\n<p class=\"MsoNormal\">exec sp_SPIDbyStatus&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#8212; all spids whith status runnable<\/p>\n<p class=\"MsoNormal\">exec sp_SPIDbyStatus &#8216;sleeping&#8217;&#160;&#160; &#8212; all spids whith status sleeping<\/p>\n<p class=\"MsoNormal\">exec sp_SPIDbyStatus &#8216;background&#8217; &#8212; all spids whith status background<\/p>\n<p class=\"MsoNormal\">exec sp_SPIDbyStatus &#8216;sleeping&#8217;&#160;&#160; &#8212; all spids whith status sleeping<\/p>\n<p class=\"MsoNormal\">exec sp_SPIDbyStatus &#8216;all&#8217;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#8212; all spids<\/p>\n<p class=\"MsoNormal\">exec sp_SPIDbyStatus &#8216;blk&#8217;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#8212; all blocked or blocking spids<\/p>\n<p class=\"MsoNormal\">exec sp_SPIDbyStatus &#8217;74&#8217;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#8212; an individual spid &#8211; also gives subthreads<\/p>\n<p class=\"MsoNormal\">select * from master..sysprocesses where spid = 56<\/p>\n<p class=\"MsoNormal\">*\/<\/p>\n<p class=\"MsoNormal\">set transaction isolation level read uncommitted<\/p>\n<p class=\"MsoNormal\">set nocount on<\/p>\n<p class=\"MsoNormal\">\n<p class=\"MsoNormal\">declare&#160;&#160;&#160;&#160;&#160;&#160; @cmd varchar(1000)<\/p>\n<p class=\"MsoNormal\">\n<p class=\"MsoNormal\">declare @buf varchar(1000) ,<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160; @id int ,<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160; @spid int ,<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160; @maxSpid int<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160; create table #spid (spid int, command varchar(1000) null)<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160; create table #temp (x varchar(100), y int, s varchar(1000), id int identity (1,1))<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160; create table #spids (spid int)<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160; if isnumeric(@status) = 1<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160; begin<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; insert #spids select @status<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160; end<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160; else if @status = &#8216;blk&#8217;<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160; begin<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; insert #spids <\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; select spid from master..sysprocesses where blocked &lt;&gt; 0<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; union<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; select blocked from master..sysprocesses where blocked &lt;&gt; 0<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160; end<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160; else<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160; begin<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; insert #spids select spid from master..sysprocesses <br \/>where (status = @status or @status = &#8216;all&#8217;) and ecid = 0<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160; end<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160; select &#160;&#160;&#160;&#160;&#160;&#160; @spid = 0 ,<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; @maxSpid = max(spid)<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160; from&#160;&#160; #spids<\/p>\n<p class=\"MsoNormal\">\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160; while @spid &lt; @maxSpid<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160; begin<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; select @spid = min(spid) from #spids where spid &gt; @spid<\/p>\n<p class=\"MsoNormal\">\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; select @cmd = &#8216;dbcc inputbuffer (&#8216; + convert(varchar(10),@spid) + &#8216;)&#8217;<\/p>\n<p class=\"MsoNormal\">\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; delete #temp<\/p>\n<p class=\"MsoNormal\">\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; insert #temp<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; exec (@cmd)<\/p>\n<p class=\"MsoNormal\">\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; select &#160;&#160;&#160;&#160;&#160;&#160; @id = 0 ,<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; @buf = &#8221;<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; select @buf = @buf + replace(replace(s,char(10),&#8217;|&#8217;),char(13),&#8217;|&#8217;)<\/p>\n<p class=\"MsoNormal\">\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; from #temp<\/p>\n<p class=\"MsoNormal\">\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; insert &#160;&#160;&#160;&#160;&#160;&#160; #spid<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; select @spid, @buf<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160; end<\/p>\n<p class=\"MsoNormal\">\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160; select &#160;&#160;&#160;&#160;&#160;&#160; blk = case when s.blocked &lt;&gt; 0 then convert(varchar(3),<br \/>s.blocked) else &#8216;&#160;&#160; &#8216; end ,<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; spid = convert(varchar(4),#spid.spid) ,<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; s.physical_io ,<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; status = left(s.status,12) ,<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; last_batch = convert(varchar(23),s.last_batch,121) ,<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; s.cmd ,<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; #spid.command ,<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; login_time = convert(varchar(23),s.login_time,121) ,<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; s.HostName<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160; from&#160;&#160; #spid ,<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; master..sysprocesses s<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160; where&#160; s.spid = #spid.spid<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160; and &#160;&#160; (ecid = 0 or isnumeric(@status) = 1)<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160; order by s.status, #spid.spid<\/p>\n<p class=\"MsoNormal\">\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160; drop table #spid<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160; drop table #temp<\/p>\n<p class=\"MsoNormal\">\n<p class=\"MsoNormal\">go<\/p>\n<p class=\"MsoNormal\">\n<p class=\"MsoNormal\">\/* And you will need a table to hold the list of blocking, <\/p>\n<p class=\"MsoNormal\">and blocked, processes *\/<\/p>\n<p class=\"MsoNormal\">\n<p class=\"MsoNormal\">CREATE TABLE [dbo].[BlockingSPids](<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160; [BlockingSpids_ID] [int] IDENTITY(1,1) NOT NULL,<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160; [blk] [varchar](3)| NOT NULL,<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160; [spid] [varchar](4)| NOT NULL,<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160; [physical_io] [int] NOT NULL,<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160; [status] [varchar](12)| NOT NULL,<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160; [last_batch] [datetime] NOT NULL,<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160; [cmd] [nchar](32)| NOT NULL,<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160; [command] [varchar](1000)| NOT NULL,<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160; [login_time] [datetime] NOT NULL,<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160; [HostName] [nchar](256)| NOT NULL,<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160; [insertionDate] [datetime] NOT NULL <\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; CONSTRAINT [DF_BlockingSPids_insertionDate] <\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; DEFAULT (getdate()),<\/p>\n<p class=\"MsoNormal\">&#160;CONSTRAINT [PK_BlockingSPids] <\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; PRIMARY KEY CLUSTERED <\/p>\n<p class=\"MsoNormal\">(<\/p>\n<p class=\"MsoNormal\">&#160;&#160;&#160;&#160;&#160;&#160; [BlockingSpids_ID] ASC<\/p>\n<p class=\"MsoNormal\">) ON [PRIMARY]<\/p>\n<p class=\"MsoNormal\">) ON [PRIMARY]<\/p>\n<p class=\"MsoNormal\">\n<p class=\"MsoNormal\">\/* finally, all you will now need to do is to place this code<\/p>\n<p class=\"MsoNormal\">on the SQL Server agent to catch and identify those Rogue Spids.*\/ <\/p>\n<p class=\"MsoNormal\">\n<p class=\"MsoNormal\">insert into BlockingSpids(<\/p>\n<p class=\"MsoNormal\">blk,spid,physical_io,status,last_batch,cmd,command,login_time,HostName)<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160; execute sp_SpidByStatus &#8216;blk&#8217; <\/p>\n<p>To keep a record of what is happening on your server you can, of course, schedule the call on the SQL Server agent and output the result of this procedure to a table. In short measure, you should have trapped the identity of that rogue process, and the other processes that it is blocking.&#8221;<\/p>\n<p>&#8220;Well, now you explain it, Rivett, it all seems so simple. How silly of me to be overawed by the problem&#8221;<\/p>\n<p>&#8220;I begin to think&#8221;, replied Rivett wistfully, &#8220;that I make a mistake in explaining. &#8216;Omne ignotum pro magnifico&#8217;. My poor reputation, such as it is, will suffer shipwreck if I am so candid.&#8221;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A process in a complex database occasionally, and apparently randomly, manages to put table locks on vital tables. Several applications are brought to a complete halt. Armed with a T-SQL stored procedure, a violin and a keen investigative spirit, Pop Rivett tracks down the rogue SPIDs that are causing all the problems&#8230;&hellip;<\/p>\n","protected":false},"author":143519,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[143531],"tags":[4728,4168,4729,4150,4183,4252,4727],"coauthors":[],"class_list":["post-242","post","type-post","status-publish","format-standard","hentry","category-t-sql-programming-sql-server","tag-blocking","tag-database","tag-spid","tag-sql","tag-t-sql","tag-t-sql-programming","tag-t-sql-stored-procedure"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/242","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/143519"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=242"}],"version-history":[{"count":3,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/242\/revisions"}],"predecessor-version":[{"id":92569,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/242\/revisions\/92569"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=242"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=242"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=242"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=242"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}