May 16, 2005 at 4:46 am
Hi all,
I've reviewed the stored procedure's around killing users - they all see somewhat similar in terms of the ACTUAL kill process - i.e. a cursor through spid's, running a KILL. that is pretty much what the code I inherited here does, as well.
http://www.sqlservercentral.com/scripts/contributions/30.asp
http://www.sqlservercentral.com/scripts/contributions/838.asp
http://www.sqlservercentral.com/scripts/contributions/1097.asp
However, this is not particularly robust, imho, since (as happened this morning) if a SPID is release between the running of the SP_WHO and the actual kill command, then the command fails:
spid ecid status loginame hostname blk dbname cmd
------ ----------- -------------------------------- -------------------------------- -------------------------------- -------- -------------------------------- ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
51 0 sleeping CORP\2020ADM 0 pdblue AWAITING COMMAND
52 0 runnable CORP\2020ADM 0 pdblue SELECT
54 0 sleeping CORP\2020ADM 0 pdblue AWAITING COMMAND
56 0 sleeping CORP\2020ADM 0 pdblue AWAITING COMMAND
65 0 sleeping CORP\2020ADM 0 pdblue AWAITING COMMAND
70 0 sleeping CORP\2020ADM 0 pdblue AWAITING COMMAND
72 0 sleeping CORP\2020ADM 0 pdblue AWAITING COMMAND
Msg 6106, Sev 16: Process ID 51 is not an active process ID. [SQLSTATE 42000]
Msg 0, Sev 16: KILL 51 [SQLSTATE 01000]
select @ReturnCode = @@Error
if @ReturnCode <> 0
Print 'A problem : '+cast(@ReturnCode as char)
else
Print 'Success : '+cast(@ReturnCode as char)
Server: Msg 6106, Level 16, State 1, Line 1
Process ID 55 is not an active process ID.
A problem : 6106
May 16, 2005 at 5:20 am
Before issuing kill command, you have to verify whether the spid is active or inactive,
you can check it by running dbcc inputbuffer that will return a rowset if the spid is active.
May 16, 2005 at 5:26 am
Thanks Allen - I'll probably do wither that, or else perhaps a simple select from sysprocesses where spid = @spid - not sure which would be more efficient...
I'm really looking to make the kill command more bullet-proof by making it handle failed kills, rather than aborting my process, and then stopping my SQL Server Agent Job.....
May 16, 2005 at 6:35 am
select from sysprocesses sounds more better.
May 17, 2005 at 12:30 am
How about Yul Wasserman's KillAllProcesses script at http://www.databasejournal.com/scripts/article.php/1491371 ?
CREATE PROCEDURE sp_KillAllProcesses
@dbname varchar (100)=NULL, /*database where we will kill processes.
If NULL-we will attempt to kill processes in all DBs*/
@UserName varchar (100)=NULL /*user in a GIVEN database or in all databases where such a user name exists,
whose processes we are going to kill. If NULL-kill all processes. */
/*Purpose: Kills all processes in a given database and/or belonging to a specified user.
If no parameters supplied it will attempt to kill all user processes on the server.
Server: all
Database: DBAservice
Created: Igor Raytsin,Yul Wasserman 2000-10-13
Last modified: Yul Wasserman 2002-02-08
source: http://www.databasejournal.com/scripts/article.php/1491371
*/
AS
SET NOCOUNT ON
DECLARE @p_id smallint
DECLARE @dbid smallint
DECLARE @db_name varchar(100)
DECLARE @exec_str varchar (255)
DECLARE @error_str varchar (255)
IF NOT EXISTS (SELECT * FROM master.dbo.sysdatabases where name=ltrim(rtrim(@dbname)) or @dbname is NULL)
BEGIN
Set @error_str='No database '+ltrim(rtrim(@dbname)) +' found.'
Raiserror(@error_str, 16,1)
RETURN-1
END
Create Table ##DbUsers(dbid smallint,uid smallint)
If @UserName is not null
BEGIN
--Search for a user in all databases or a given one
DECLARE curDbUsers CURSOR FOR
SELECT dbid,name FROM master.dbo.sysdatabases where name=ltrim(rtrim(@dbname)) or @dbname is NULL
OPEN curDbUsers
FETCH NEXT FROM curDbUsers INTO @dbid,@db_name
WHILE @@FETCH_STATUS = 0
BEGIN
SELECT @exec_str='Set quoted_identifier off
INSERT ##DbUsers SELECT '+cast(@dbid as char)+', uid FROM '+@db_name+'.dbo.sysusers
WHERE name="'+ltrim(rtrim(@UserName))+'"'
EXEC (@exec_str)
FETCH NEXT FROM curDbUsers INTO @dbid,@db_name
END
CLOSE curDbUsers
DEALLOCATE curDbUsers
If not exists(Select * from ##DbUsers)
BEGIN
Set @error_str='No user '+ltrim(rtrim(@UserName)) +' found.'
DROP TABLE ##DbUsers
Raiserror(@error_str, 16,1)
RETURN-1
END
END
ELSE --IF @UserName is null
BEGIN
INSERT ##DbUsers SELECT ISNULL(db_id(ltrim(rtrim(@dbname))),-911),-911
END
--select * from ##dbUsers
DECLARE curAllProc CURSOR FOR
SELECT spid,sp.dbid FROM master.dbo.sysprocesses sp
INNER JOIN ##DbUsers t ON (sp.dbid = t.dbid or t.dbid=-911) and (sp.uid=t.uid or t.uid=-911)
OPEN curAllProc
FETCH NEXT FROM curAllProc INTO @p_id, @dbid
WHILE @@FETCH_STATUS = 0
BEGIN
SELECT @exec_str = 'KILL '+ Convert(varchar,@p_id)+ ' checkpoint'
SELECT @error_str = 'Attempting to kill process '+Convert(varchar,@p_id)+' in database '+db_name(@dbid)
RAISERROR (@error_str,10,1)with log
EXEC (@exec_str)
FETCH NEXT FROM curAllProc INTO @p_id, @dbid
END
CLOSE curAllProc
DEALLOCATE curAllProc
DROP TABLE ##DbUsers
SET NOCOUNT OFF
G. Milner
May 17, 2005 at 2:12 am
Hmm - interesting difference's. BOL doesn;t describe the +checkpoint option for Kill - I'll have to see what that does. Also, I see he log's each attempted kill.
But still no @@error checking on failure. I'm trying to see if it works and how well. Oh well, off to test I go
Viewing 6 posts - 1 through 5 (of 5 total)
You must be logged in to reply to this topic. Login to reply