4

我想修改以下内容,因为它似乎没有杀死进程 - 我认为它应该断开用户的连接(这是一样的吗?)。我希望能够杀死特定数据库的所有进程 - 如何修改以下内容:

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

更新

以上不起作用,即它不会终止进程。

它不会杀死进程。我查看活动监视器,它仍然显示该过程仍在继续,我可以看到我的查询仍在查询窗口中工作。当我执行“kill 53”时,查询窗口中的查询停止并且进程从活动监视器中消失了!所以杀死工作但不是这个程序为什么?

4

6 回答 6

3

您是否只是想停止特定数据库上的所有活动,以便对其进行一些维护?

如果是这样,您可以执行以下操作:

ALTER DATABASE myDB SET SINGLE_USER WITH ROLLBACK IMMEDIATE;

这将杀死所有其他访问数据库的 SPID,并将数据库置于单用户模式。然后执行您的维护操作,然后执行以下操作:

ALTER DATABASE myDB SET MULTI_USER;
于 2009-12-08T03:18:03.527 回答
2

我对这个脚本很熟悉。它会杀死所有使用数据库的 SPID,是的。您需要在正确的权限下运行它——不仅仅是任何用户都可以杀死 SPID。

此外,您可能有应用程序尝试并保持与数据库的持久连接,因此可能会在您终止其 SPID 后不久重新连接。

于 2009-11-27T12:10:15.157 回答
0

您可能想尝试使用 exec 而不是 sp_exec (不是说它应该有任何区别)

SET @killstatement = 'KILL ' + cast(@spid as varchar(3)) 
EXEC (@killstatement)
于 2009-11-30T07:18:55.347 回答
0

您是否尝试过任何调试/输出程序运行时实际发生的情况?例如,您可以修改 @killstatement 以声明为 nvarchar(max) 并包含一些详细输出,例如以下内容并发布结果吗?基本上用以下内容替换开始/结束块中的所有内容:

-- 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;

如果您可以发布结果,希望这会给我们一些继续下去的机会。

于 2009-12-03T16:18:53.473 回答
0

很可能这些都不适用于您,但以防万一几年前我在处理此类事情时遇到了一些奇怪的情况(所有 SQL 2005)。

  • 你不能杀死自己的连接。
  • 在我使用的代码中,我确保永远不会尝试杀死任何低于 51 的 spid。(这些是系统连接;我不知道它们是否可以被杀死,但我不会尝试。)
  • 如果一个连接正在处理一个事务,它必须在它被杀死之前回滚那个事务。大量事务可能需要大量时间才能回滚。
  • 小心连接池。他们就像不死生物——杀了他们,他们就会马上回来,通常在一秒钟之内。

在运行此过程时运行 SQL Profiler 并跟踪登录和注销可能会发现问题,尤其是对于连接池问题。

于 2009-12-07T16:22:46.663 回答
0

这在 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
于 2009-12-08T07:20:10.717 回答