문제

프로세스를 죽이지 않는 것처럼 다음을 수정하고 싶습니다. 사용자를 분리해야한다고 생각합니다 (동일합니까?). 특정 데이터베이스의 모든 프로세스를 죽일 수 있기를 원합니다. 아래를 어떻게 수정할 수 있습니까?

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
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top