SQL Server : 저장 프로 시저를 사용하여 프로세스 킬
-
05-07-2019 - |
문제
프로세스를 죽이지 않는 것처럼 다음을 수정하고 싶습니다. 사용자를 분리해야한다고 생각합니다 (동일합니까?). 특정 데이터베이스의 모든 프로세스를 죽일 수 있기를 원합니다. 아래를 어떻게 수정할 수 있습니까?
create procedure [dbo].[sp_killusers](@database varchar(30))
as
----------------------------------------------------
-- * Created By David Wiseman, Updated 19/11/2006
-- * http://www.wisesoft.co.uk
-- * This procedure takes the name of a database as input
-- * and uses the kill statment to disconnect them from
-- * the database.
-- * PLEASE USE WITH CAUTION!!
-- * Usage:
-- * exec sp_killusers 'databasename'
----------------------------------------------------
set nocount on
declare @spid int
declare @killstatement nvarchar(10)
-- Declare a cursor to select the users connected to the specified database
declare c1 cursor for select request_session_id
from sys.dm_tran_locks
where resource_type='DATABASE'
AND DB_NAME(resource_database_id) = @database
open c1
fetch next from c1 into @spid
-- for each spid...
while @@FETCH_STATUS = 0
begin
-- Don't kill the connection of the user executing this statement
IF @@SPID <> @spid
begin
-- Construct dynamic sql to kill spid
set @killstatement = 'KILL ' + cast(@spid as varchar(3))
exec sp_executesql @killstatement
-- Print killed spid
print @spid
end
fetch next from c1 into @spid
end
-- Clean up
close c1
deallocate c1
업데이트
위의 일은 작동하지 않습니다. 즉, 프로세스를 죽이지 않습니다.
과정을 죽이지 않습니다. Activity Monitor를보고 여전히 프로세스가 계속 표시되며 쿼리가 여전히 쿼리 창에서 작동하는 것을 볼 수 있습니다. "Kill 53"을 할 때 쿼리가 쿼리 창에서 중지되고 프로세스가 활동 모니터에서 사라집니다! 그래서이 절차는 그 이유는 없지만 왜이 절차는 아니야?
해결책
이 대본에 익숙합니다. 데이터베이스를 사용하는 모든 SPID를 죽입니다. 사용자는 SPID를 죽일 수있는 것이 아니라 올바른 권한에 따라 실행해야합니다.
또한 DB와의 지속적인 연결을 유지하려고 시도하는 응용 프로그램이있을 수 있으므로 SPID를 죽인 직후 다시 연결할 수 있습니다.
다른 팁
특정 DB의 모든 활동을 중지하여 유지 보수를 수행 할 수 있습니까?
그렇다면 다음을 수행 할 수 있습니다.
ALTER DATABASE myDB SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
이것은 DB에 액세스하는 다른 모든 SPID를 죽이고 DB를 단일 사용자 모드로 배치합니다. 그런 다음 유지 보수 조치를 수행하고 다음을 수행하십시오.
ALTER DATABASE myDB SET MULTI_USER;
sp_exec 대신 exec를 사용해 볼 수 있습니다 (차이가 없어야합니다).
SET @killstatement = 'KILL ' + cast(@spid as varchar(3))
EXEC (@killstatement)
절차가 실행될 때 실제로 발생하는 일에 대한 디버깅/출력을 시도해 보셨습니까? 예를 들어, nvarchar (max)로 선언되도록 @killstatement를 수정하고 다음과 같은 일부 장황한 출력을 포함시키고 결과를 게시 할 수 있습니까? 기본적으로 시작/종료 블록 내의 모든 것을 다음과 같은 것으로 바꿉니다.
-- Construct dynamic sql to kill spid
select @killstatement = N'
select *
from sys.dm_exec_sessions s
join sys.dm_exec_connections c
on s.session_id = c.session_id
where c.session_id = @spid;
kill ' + cast(@spid as varchar(3)) + ';
select *
from sys.dm_exec_sessions s
join sys.dm_exec_connections c
on s.session_id = c.session_id
where c.session_id = @spid;
';
-- Print & Exec
print @killstatement;
exec sp_executesql @killstatement, N'@spid smallint', @spid;
print @spid;
절차 코드 내에서 다르게 행동해야 할 이유가 없습니다. 연결 내에서 명시 적으로 실행하는 것 - 적절한 권한이 있고 유효한 SPID 등을 죽이고 있다고 가정하면 위와 같은 디버깅 결과를 게시 할 수있는 경우 ( 그리고 당신이 시도했을 수도있는 다른 것은) 문제가 어디에 있는지 파악하는 데 도움이 될 것입니다. 커서 선언 결과의 디버그 출력을 포함시킬 수도 있습니다. 다음과 같은 결과 세트 :
declare c1 cursor for select request_session_id
from sys.dm_tran_locks
where resource_type='DATABASE'
AND DB_NAME(resource_database_id) = @database
-- Debug output - sessions we should try and kill...
select request_session_id
from sys.dm_tran_locks
where resource_type='DATABASE'
AND DB_NAME(resource_database_id) = @database;
결과를 게시 할 수 있다면, 우리에게 계속할 무언가를 줄 수 있기를 바랍니다.
이들 중 어느 것도 당신에게 적용되지 않을 확률이 좋지만, 여기에 몇 년 전 이와 같은 일을 할 때 겪은 홀수 볼 상황이있는 경우 (All SQL 2005).
- 자신의 연결을 죽일 수 없습니다.
- 내가 사용한 코드에서 절대 51 세 미만의 SPID를 시도하고 죽이십시오. (이것은 시스템 연결입니다. 나는 그들이 죽일 수 있는지 모르겠지만 시도하지는 않을 것입니다.)
- 연결이 트랜잭션을 처리하는 경우 거래를 죽이기 전에 해당 트랜잭션을 다시 굴려야합니다. 막대한 거래는 롤백하는 데 상당한 시간이 걸릴 수 있습니다.
- 연결 풀링을 조심하십시오. 그들은 언데드와 같습니다.
이 프로세스를 실행하는 동안 SQL 프로파일 러를 실행하고 로그인 및 로그 아웃을 추적하면 특히 연결 풀링 문제에 대해 공개 될 수 있습니다.
이것은 SQLSERVER 2000에서 저에게 효과가 있습니다
DECLARE @DbName VARCHAR(100)
DECLARE @SPID INT
DECLARE @TranUOW UNIQUEIDENTIFIER
DECLARE @KillStmt NVARCHAR(100)
SET @DbName = 'MyDatabase'
-----------------------------------
-- Kill distributed transactions
DECLARE dist CURSOR FOR
SELECT DISTINCT req_transactionUOW
FROM master..syslockinfo
WHERE db_name(rsc_dbid) = @DbName
AND req_transactionUOW <> '00000000-0000-0000-0000-000000000000'
OPEN dist
FETCH NEXT FROM dist INTO @TranUOW
WHILE @@FETCH_STATUS = 0
BEGIN
SET @KillStmt = 'kill ''' + CAST(@TranUOW AS VARCHAR(50)) + ''''
PRINT @KillStmt
EXECUTE(@KillStmt)
FETCH NEXT FROM dist INTO @TranUOW
END
CLOSE dist
DEALLOCATE dist
-----------------------------------
-- Kill user connections
DECLARE cur CURSOR FOR
SELECT spid
FROM master..sysprocesses
WHERE db_name(dbid) = @DbName
AND spid > 50
OPEN cur
FETCH NEXT FROM cur INTO @SPID
WHILE @@FETCH_STATUS = 0
BEGIN
SET @KillStmt = 'kill ' + CAST(@SPID AS VARCHAR(10))
PRINT @KillStmt
EXECUTE(@KillStmt)
FETCH NEXT FROM cur INTO @SPID
END
CLOSE cur
DEALLOCATE cur