Technical Article

Kill all SPIDs with a certain user ID

,

This script is used to disconnect all connections by a particular individual to a server. I use it when I have to disconnect somebody and they have too many processes to do it by hand. Normally, you can just connect the offending process, but if there are multiple processes that are causing a problem , you can use this script to just disconnect the user from the server.

If you run this procedure without any parameters, it will return a list of all active connections, along with the number of databases they're using and the number of connections they have. If you run it with a loginname as a parameter, it will kill all the instances of that login name.

WARNING - ANY UNCOMMITTED TRANSACTIONS WILL BE ROLLED BACK, SO USE CAREFULLY!

SET QUOTED_IDENTIFIER ON 
GO
SET ANSI_NULLS ON 
GO



/*	AUTHOR:	RMcCauley (with some help from Microsoft)
	CREATED:	10/17/2003
	PURPOSE:	This procedure is user to kill multiple user processes
		at once. If run without a parameter, it will list each
		user currently connected, as well as the total number
		of processes and databases their connected to. Run it
		again with that person's login as a parameter, and the
		procedure will shred each of that person's processes,
		releasing their QA session to execute more poorly
		planned and horribly un-optimized queries.

         SIDE NOTE:	Don't kill the 'sa' user - that's bad.
*/


ALTER         PROCEDURE sp_killuser -- 1995/11/03 10:16
	@loginame     sysname = NULL
as

IF @loginame like 'sa'
BEGIN
	Print 'You can''t kill the SA user!'
	GOTO LABEL_86RETURN
END



set nocount on

declare
    @retcode         int

declare
    @sidlow         varbinary(85)
   ,@sidhigh        varbinary(85)
   ,@sid1           varbinary(85)
   ,@spidlow         int
   ,@spidhigh        int

declare
    @charMaxLenLoginName      varchar(6)
   ,@charMaxLenDBName         varchar(6)
   ,@charMaxLenCPUTime        varchar(10)
   ,@charMaxLenDiskIO         varchar(10)
   ,@charMaxLenHostName       varchar(10)
   ,@charMaxLenProgramName    varchar(10)
   ,@charMaxLenLastBatch      varchar(10)
   ,@charMaxLenCommand        varchar(10)

declare
    @charsidlow              varchar(85)
   ,@charsidhigh             varchar(85)
   ,@charspidlow              varchar(11)
   ,@charspidhigh             varchar(11)

DECLARE @current_process 	int

--------

select
    @retcode         = 0      -- 0=good ,1=bad.

--------defaults
select @sidlow = convert(varbinary(85), (replicate(char(0), 85)))
select @sidhigh = convert(varbinary(85), (replicate(char(1), 85)))

select
    @spidlow         = 0
   ,@spidhigh        = 32767

--------------------------------------------------------------
IF (@loginame IS     NULL)  --Simple default to all LoginNames.
      GOTO LABEL_17PARM1EDITED

--------

-- select @sid1 = suser_sid(@loginame)
select @sid1 = null
if exists(select * from master.dbo.syslogins where loginname = @loginame)
	select @sid1 = sid from master.dbo.syslogins where loginname = @loginame

IF (@sid1 IS NOT NULL)  --Parm is a recognized login name.
   begin
   select @sidlow  = suser_sid(@loginame)
         ,@sidhigh = suser_sid(@loginame)
   GOTO LABEL_17PARM1EDITED
   end

--------

IF (lower(@loginame) IN ('active'))  --Special action, not sleeping.
   begin
   select @loginame = lower(@loginame)
   GOTO LABEL_17PARM1EDITED
   end

--------

IF (patindex ('%[^0-9]%' , isnull(@loginame,'z')) = 0)  --Is a number.
   begin
   select
             @spidlow   = convert(int, @loginame)
            ,@spidhigh  = convert(int, @loginame)
   GOTO LABEL_17PARM1EDITED
   end

--------

/*RaisError(15007,-1,-1,@loginame)
select @retcode = 1
GOTO LABEL_86RETURN
*/

LABEL_17PARM1EDITED:


--------------------  Capture consistent sysprocesses.  -------------------

SELECT

  spid
 ,status
 ,sid
 ,hostname
 ,program_name
 ,cmd
 ,cpu
 ,physical_io
 ,blocked
 ,dbid
 ,convert(sysname, rtrim(loginame))
        as loginname
 ,spid as 'spid_sort'

 ,  substring( convert(varchar,last_batch,111) ,6  ,5 ) + ' '
  + substring( convert(varchar,last_batch,113) ,13 ,8 )
       as 'last_batch_char'

      INTO    #tb1_sysprocesses
      from master.dbo.sysprocesses   (nolock)



--------Screen out any rows?

IF (@loginame IN ('active'))
   DELETE #tb1_sysprocesses
         where   lower(status)  = 'sleeping'
         and     upper(cmd)    IN (
                     'AWAITING COMMAND'
                    ,'MIRROR HANDLER'
                    ,'LAZY WRITER'
                    ,'CHECKPOINT SLEEP'
                    ,'RA MANAGER'
                                  )

         and     blocked       = 0



--------Prepare to dynamically optimize column widths.


Select
    @charsidlow     = convert(varchar(85),@sidlow)
   ,@charsidhigh    = convert(varchar(85),@sidhigh)
   ,@charspidlow     = convert(varchar,@spidlow)
   ,@charspidhigh    = convert(varchar,@spidhigh)



SELECT
             @charMaxLenLoginName =
                  convert( varchar
                          ,isnull( max( datalength(loginname)) ,5)
                         )

            ,@charMaxLenDBName    =
                  convert( varchar
                          ,isnull( max( datalength( rtrim(convert(varchar(128),db_name(dbid))))) ,6)
                         )

            ,@charMaxLenCPUTime   =
                  convert( varchar
                          ,isnull( max( datalength( rtrim(convert(varchar(128),cpu)))) ,7)
                         )

            ,@charMaxLenDiskIO    =
                  convert( varchar
                          ,isnull( max( datalength( rtrim(convert(varchar(128),physical_io)))) ,6)
                         )

            ,@charMaxLenCommand  =
                  convert( varchar
                          ,isnull( max( datalength( rtrim(convert(varchar(128),cmd)))) ,7)
                         )

            ,@charMaxLenHostName  =
                  convert( varchar
                          ,isnull( max( datalength( rtrim(convert(varchar(128),hostname)))) ,8)
                         )

            ,@charMaxLenProgramName =
                  convert( varchar
                          ,isnull( max( datalength( rtrim(convert(varchar(128),program_name)))) ,11)
                         )

            ,@charMaxLenLastBatch =
                  convert( varchar
                          ,isnull( max( datalength( rtrim(convert(varchar(128),last_batch_char)))) ,9)
                         )
      from
             #tb1_sysprocesses
      where
--             sid >= @sidlow
--      and    sid <= @sidhigh
--      and
             spid >= @spidlow
      and    spid <= @spidhigh
 
IF @loginame is null
BEGIN      
	--------Output the report.
	   SELECT count(spid) as Sessions,
		null as databases,
	          sp.loginname as Login
	     into #results
	     from #tb1_sysprocesses sp
	    where spid >=  @charspidlow
	      and spid <= @charspidhigh
	      --and loginname <> 'sa'
	 GROUP BY sp.loginname
		
	-- Create list of databases to see how many each person is using
		   select count(db) as dbcount,
		loginname
	     INTO	#dbusernames
	     from (select distinct db_name(dbid) as db, loginname from #tb1_sysprocesses) small
	 GROUP BY loginname
	
	-- Join to database names
	UPDATE #results
	SET databases = db.dbcount
	FROM #results, #dbusernames db
	WHERE #results.login = db.loginname
	
	-- Return results
	SELECT * from #results

END
IF @loginame is not null --Do the actual process killing
BEGIN
	DECLARE kill_cursor SCROLL CURSOR
	 FOR
	   SELECT spid
	     from #tb1_sysprocesses sp
	    where spid >=  @charspidlow
	      and spid <= @charspidhigh
	      and upper(loginname) = upper(@loginame)

	--open the cursor	
	OPEN kill_cursor

	--fetch first variables from cursor
	FETCH FIRST FROM kill_cursor
	 INTO @current_process

	PRINT 'Killing all processes for user ' + @loginame
	--While there is no error fetching rows insert data into #data table.
	WHILE @@FETCH_STATUS = 0
	BEGIN
		EXEC ('kill ' + @current_process)
		Print 'Successfully killed process number ' + @current_process
		FETCH NEXT FROM kill_cursor
		 INTO @current_process
	END
	PRINT 'All processes for ' + @loginame + ' have been killed'

	CLOSE kill_cursor
	DEALLOCATE kill_cursor

END

SET nocount on


LABEL_86RETURN:


if (object_id('tempdb..#tb1_sysprocesses') is not null)
BEGIN
	drop table #tb1_sysprocesses
	if @loginame is null
	BEGIN		
		DROP TABLE #dbusernames
		DROP TABLE #results
	END
END



GO
SET QUOTED_IDENTIFIER OFF 
GO
SET ANSI_NULLS ON 
GO

Rate

You rated this post out of 5. Change rating

Share

Share

Rate

You rated this post out of 5. Change rating