Frage

Ich möchte Folgendes ändern, da es keine Prozesse zu töten scheint - ich denke, es soll Benutzer trennen (ist das gleich?). Ich möchte in der Lage sein, den gesamten Prozess für eine bestimmte Datenbank zu töten - wie kann ich die folgenden ändern:

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

Aktualisieren

Das obige funktioniert nicht, dh es tötet den Prozess nicht.

Es tötet den Prozess nicht. Ich schaue mir den Aktivitätsmonitor an und es zeigt immer noch den Prozess, der weitergeht, und ich kann sehen, dass meine Abfrage immer noch im Abfragefenster funktioniert. Wenn ich "töte 53", stoppt die Abfrage im Abfragefenster und der Prozess ist vom Aktivitätsmonitor verschwunden! Also funktioniert töten, aber nicht dieses Verfahren Warum?

War es hilfreich?

Lösung

Ich bin mit diesem Skript vertraut. Es tötet alle Spids, die eine Datenbank verwenden, ja. Sie müssen es unter den richtigen Berechtigungen ausführen - nicht irgendein Benutzer kann Spids töten.

Es besteht auch die Möglichkeit, dass Sie möglicherweise Anwendungen haben, die versuchen, anhaltende Verbindungen zum DB aufrechtzuerhalten, und daher möglicherweise kurz nach dem Töten ihrer Spid wieder verbinden.

Andere Tipps

Versuchen Sie nur, alle Aktivitäten auf einem bestimmten DB zu stoppen, damit Sie es gewartet haben können?

Wenn ja, können Sie Folgendes tun:

ALTER DATABASE myDB SET SINGLE_USER WITH ROLLBACK IMMEDIATE;

Dies tötet alle anderen Spids, die auf die DB zugreifen, und setzen die DB im Einzelbenutzermodus. Führen Sie dann Ihre Wartungsmaßnahmen aus und führen Sie Folgendes an:

ALTER DATABASE myDB SET MULTI_USER;

Vielleicht möchten Sie versuchen, EXEC anstelle von SP_EXEC zu verwenden (nicht, dass es einen Unterschied machen sollte)

SET @killstatement = 'KILL ' + cast(@spid as varchar(3)) 
EXEC (@killstatement)

Haben Sie versucht, das Debugging/Output dessen zu debugieren, was tatsächlich auftritt, wenn das Verfahren ausgeführt wird? Können Sie beispielsweise @KillStatement so ändern, dass Sie als Nvarchar (MAX) deklariert werden und einige ausführliche Ausgaben wie die folgenden Faktoren einfügen und die Ergebnisse veröffentlichen? Ersetzen Sie im Grunde alles in Ihrem Beginn/Endblock durch so etwas wie:

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

Es gibt keinen Grund, warum sich im Verfahrenscode etwas anders verhalten sollte als die ausdrückliche Ausführung in einer Verbindung - vorausgesetzt, Sie haben die entsprechenden Berechtigungen, töten gültige Spids usw. usw. Wenn Sie die Ergebnisse einiger Debugging wie das oben genannte veröffentlichen können (oben genannte Und alles andere, was Sie vielleicht ausprobiert haben), würde helfen, herauszufinden, wo sich das Problem befindet. Möglicherweise möchten Sie auch eine Debug -Ausgabe der Ergebnisse des Cursor -Deklars angeben, mit dem Sie sicherstellen, dass Sie tatsächlich die Sitzungen erhalten, die Sie töten möchten. Ergebnis -Set wie dieses:

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;

Wenn Sie die Ergebnisse veröffentlichen können, erhalten wir hoffentlich etwas, das wir weitermachen können.

Die Chancen stehen gut, dass keines davon für Sie zutreffend ist, aber für den Fall, dass hier einige seltsame Situationen aufgenommen werden, habe ich vor ein paar Jahren an solchen Dingen gearbeitet (alle SQL 2005).

  • Sie können Ihre eigene Verbindung nicht töten.
  • In dem Code, den ich verwendet habe, habe ich dafür gesorgt noch nie Versuchen Sie, einen Spid unter 51 zu töten. (Dies sind Systemverbindungen; ich weiß nicht, ob sie getötet werden können, aber ich würde es nicht versuchen.)
  • Wenn eine Verbindung eine Transaktion verarbeitet, muss sie diese Transaktion zurückrollen, bevor sie getötet werden kann. Riesige Transaktionen können erhebliche Zeit in Anspruch nehmen, um zurückzurollen.
  • Achten Sie auf die Verbindung zu Pooling. Sie sind wie die Untoten-kürzen Sie sie und sie kommen einfach gleich zurück, oft in einer Sekunde.

Ausführen von SQL -Profiler und Verfolgung von Logins und Abmeldungen beim Ausführen dieses Vorgangs ist möglicherweise aufzeigt, insbesondere für Probleme mit Verbindungen.

Dies funktioniert für mich in 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
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top